今天遇到一个问题,需要在service中写一个方法,从A方法里面循环调用B方法,在B方法里面添加事务注解@Transactional。但是测试无效。事务并不回滚。
在网上找了很多办法:
首先是数据库(mysql存储引擎要为InnoDB)
手动try。catch需要再次手动抛RuntimeException异常,@Transactional加上rollbackFor = Exception.class
手动回滚,代码catch中加上TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 但是结果并没有回滚,反而报错: No transaction aspect-managed TransactionStatus in scope (意思是这个类里面没有事务,不能进行手动回滚)
尝试过以上方法后都无效。后来在一个博客中看到
事务没有回滚可能是因为写在同一个类里
, 然后我就试了新建一个Service ,将方法B中的业务逻辑放到这个新建的Service中并加上事务 ,问题解决。
在那篇博客中看到的原因是: Spring之所以可以对开启@Transactional的方法进行事务管理,是因为Spring为当前类生成了一个代理类,然后在执行相关方法时,会判断这个方法有没有@Transactional注解,如果有的话,则会开启一个事务。
但是,上面同一个类中A调用方式时,在调用B时,使用的并不是代理对象,从而导致this.B(i)时也不是代理对象,从而导致@Transactional失败。所以,Spring 从同一个类中的某个方法调用另一个有注解(@Transactional)的方法时,事务会失效,些事务的时候一定要注意到这一点。