当前位置:   article > 正文

Java不同的service间的方法调用,如何保证事务全部回滚_不同类的事务调用会回滚吗

不同类的事务调用会回滚吗

最近在代码重构时,将一些复杂的service层方法,进行抽象,公共部分提取到父类中,但是因此遇到一个问题,就是方法被拆分后(部分逻辑提取到父类中),当发生异常时,整个逻辑中部分数据库操作不会回滚,经过一系列测试及资料查阅,最终才得以解决。

举例1:

  1. @Service
  2. public abstract class BaseService {
  3. public void method1(){
  4. method2();
  5. }
  6. public abstract void method2();
  7. @Transactional(rollbackFor = Exception.class)
  8. public void method3(){
  9. insert(Object object);
  10. System.out.println("------");
  11. }
  12. }
  13. @Service
  14. public class IBaseServiceImpl extends BaseService {
  15. @Override
  16. @Transactional(rollbackFor = Exception.class)
  17. public void method2() {
  18. insert(Object object);
  19. method3();
  20. }
  21. }

当调用BaseService的method1时,如果method3中抛出异常时,各个方法内的db操作回滚情况如下:

method2():不回滚

method3():不回滚

method2()和method3()均有事务注解标识,为什么没有全部回滚呢?

因为spring的事务是基于aop实现的,aop的底层又是动态代理,在method1中调用method2时,method2的调用并不是直接通过代理对象的方式调用的,所以method2即便标注了事务注解,事务也不会生效(而直接通过IBaseServiceImpl

.method2调用时,才会被代理),method3也是同样的道理。

所以,为了保证事务生效,我们在调用方法时,需要利用AopContext.currentProxy(),拿到当前线程的代理对象来请求被调用类的方法,被调用的方法才会被代理,所以上述代码改成如下方式时,事务就会生效了:

  1. @Service
  2. public abstract class BaseService {
  3. public void method1(){
  4. ((BaseService)AopContext.currentProxy()).method2();
  5. }
  6. public abstract void method2();
  7. @Transactional(rollbackFor = Exception.class)
  8. public void method3(){
  9. System.out.println("------");
  10. }
  11. }
  12. @Service
  13. public class IBaseServiceImpl extends BaseService {
  14. @Override
  15. @Transactional(rollbackFor = Exception.class)
  16. public void method2() {
  17. ((BaseService) AopContext.currentProxy()).method3();
  18. }
  19. }

经过测试,method2、method3的事务均生效。

至于spring事务的传播机制及回滚异常的指定,本文就不重复描述,可以参考网上其它文章。

网上很多文章介绍的都是同一个类中方法调用的事务问题,关于跨类调用的,介绍的很少,希望这篇文章可以帮助遇到同类问题的兄弟们!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/224716
推荐阅读
相关标签
  

闽ICP备14008679号