携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情
@Transactional注解在方法间调用
前文
在@Transactional注解的使用中,经常会遇到需要在方法间调用的情况。当在不同方法间进行调用时,经常会出现事务失败的情况。本文将针对该注解在方法间的调用相关内容进行总结。
在方法中如何进行@Transactional注解调用
下面根据不同的调用方式,分析该注解的生效及不生效情况。
- 在直接调用的方法上直接添加注解,在被调用的方法上不加注解
@Transactional(rollbackFor = Exception.class)
public Object test() {
this.test1();
// applicationContext.getBean(TestTransactionalService.class).test1();
return "success";
}
// @Transactional(rollbackFor = Exception.class)
public Object test1() {
TestTransactionalPO testTransactionalPO = new TestTransactionalPO();
testTransactionalPO.setId(3L);
testTransactionalPO.setName("a");
testTransactionalMapper.addData(testTransactionalPO);
throw new RestApiException(ExceptionInfoEnum.DATA_NOT_FOUND_EXCEPTION);
}
这种方式事务生效,也就是只要我们在通过bean直接调用的对象方法上增加注解,即可完成回滚。使用this调用时采用的依然是被切面包装过的对象。
- 在直接调用的方法上加注解,在被调用的方法上加注解
@Transactional(rollbackFor = Exception.class)
public Object test() {
this.test1();
// applicationContext.getBean(TestTransactionalService.class).test1();
return "success";
}
@Transactional(rollbackFor = Exception.class)
public Object test1() {
TestTransactionalPO testTransactionalPO = new TestTransactionalPO();
testTransactionalPO.setId(3L);
testTransactionalPO.setName("a");
testTransactionalMapper.addData(testTransactionalPO);
throw new RestApiException(ExceptionInfoEnum.DATA_NOT_FOUND_EXCEPTION);
}
在bean直接调用的方法上使用注解,同时在被调用的方法上使用注解,该事务同样是生效的。由于事务的传播机制,按照默认的方法,这种情况下两者的注解采用的是相同的事务。
- 在直接调用的方法不加注解,在被调用的方法上增加注解
public Object test() {
this.test1();
// applicationContext.getBean(TestTransactionalService.class).test1();
return "success";
}
@Transactional(rollbackFor = Exception.class)
public Object test1() {
TestTransactionalPO testTransactionalPO = new TestTransactionalPO();
testTransactionalPO.setId(3L);
testTransactionalPO.setName("a");
testTransactionalMapper.addData(testTransactionalPO);
throw new RestApiException(ExceptionInfoEnum.DATA_NOT_FOUND_EXCEPTION);
}
在bean直接调用方法上不使用注解,而在被调用的方法上使用注解。如果我们采用this进行调用,事务是不生效的。而如果我们采用applicationContext.getBean(TestTransactionalService.class)的方式获取bean对象,再进行调用,则该事务是生效的。原因是实际的该注解是作用在动态代理对象上的,如果我们采用this直接调用并非动态代理对象,也就会导致注解失效。cache、aop等都存在该问题。
额外补充
在多线程的应用场景下,该注解是不生效的。如果多线程需要进行事务回滚操作,需要我们在代码内手动进行回滚。
后记
- 千古兴亡多少事?悠悠。不尽长江滚滚流。