赞
踩
最近在代码重构时,将一些复杂的service层方法,进行抽象,公共部分提取到父类中,但是因此遇到一个问题,就是方法被拆分后(部分逻辑提取到父类中),当发生异常时,整个逻辑中部分数据库操作不会回滚,经过一系列测试及资料查阅,最终才得以解决。
举例1:
- @Service
- public abstract class BaseService {
-
- public void method1(){
- method2();
- }
-
- public abstract void method2();
-
- @Transactional(rollbackFor = Exception.class)
- public void method3(){
- insert(Object object);
- System.out.println("------");
- }
- }
-
- @Service
- public class IBaseServiceImpl extends BaseService {
- @Override
- @Transactional(rollbackFor = Exception.class)
- public void method2() {
- insert(Object object);
- method3();
- }
- }

当调用BaseService的method1时,如果method3中抛出异常时,各个方法内的db操作回滚情况如下:
method2():不回滚
method3():不回滚
method2()和method3()均有事务注解标识,为什么没有全部回滚呢?
因为spring的事务是基于aop实现的,aop的底层又是动态代理,在method1中调用method2时,method2的调用并不是直接通过代理对象的方式调用的,所以method2即便标注了事务注解,事务也不会生效(而直接通过IBaseServiceImpl
.method2调用时,才会被代理),method3也是同样的道理。
所以,为了保证事务生效,我们在调用方法时,需要利用AopContext.currentProxy(),拿到当前线程的代理对象来请求被调用类的方法,被调用的方法才会被代理,所以上述代码改成如下方式时,事务就会生效了:
- @Service
- public abstract class BaseService {
-
- public void method1(){
- ((BaseService)AopContext.currentProxy()).method2();
- }
-
- public abstract void method2();
-
- @Transactional(rollbackFor = Exception.class)
- public void method3(){
- System.out.println("------");
- }
- }
-
- @Service
- public class IBaseServiceImpl extends BaseService {
- @Override
- @Transactional(rollbackFor = Exception.class)
- public void method2() {
- ((BaseService) AopContext.currentProxy()).method3();
- }
- }

经过测试,method2、method3的事务均生效。
至于spring事务的传播机制及回滚异常的指定,本文就不重复描述,可以参考网上其它文章。
网上很多文章介绍的都是同一个类中方法调用的事务问题,关于跨类调用的,介绍的很少,希望这篇文章可以帮助遇到同类问题的兄弟们!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。