嵌套事务被提交的情况

当ServiceA.method_a调用ServiceB.method_b时,ServiceB内的事务无法独立回滚,导致更新表a1及存储过程c的改动在A3失败时无法回滚。问题源于Spring事务的动态代理特性,使得内部调用不产生新的事务。为确保逻辑A1、A2不受A3影响,需在A2后手动提交事务。但如何处理存储过程的提交行为仍是一个疑问,目前寻找解决方案中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

class ServiceA{
    method_a(){   //PROPAGATION_REQUIRED
        逻辑 A1{
            更新表a1; 
        }
        逻辑 A2{
            ServiceB.method_b();
        }
        逻辑 A3{
            更新表a2; 
        }
    }
}

class ServiceB{
     method_b(){      
         ServiceC.method_c
         更新表b; 
     }
}

class ServiceC{
    method_c(){ //PROPAGATION_REQUIRES_NEW
         存储过程c(显式执行commit); 
     }
}

现状

         ServiceA.method_a本身有事务,里面调用ServiceB.method_b,另起新事务。 执行逻辑A3时,更新表a2失败。只回滚了ServiceB里面的更新表b,无法回滚更新表a1及存储过程c。

目的   

          业务场景中的目的是,无论逻辑A3报什么错,都不能影响逻辑A1、A2

           只要在逻辑A2后,手动提交事务即可【已解决】

疑问

         逻辑A1为什么会被存储过程一起commit了,无法再回滚?

分析

           Spring事务管理是通过JDK动态代理的方式进行实现的(另一种是使用CGLib动态代理实现的),也正是因为动态代理的特性造成了上述方法中的新开事务失效!只有代理对象proxy直接调用的那个方法才是真正的走代理的,嵌套的方法实际上就是 直接把嵌套的代码移动到代理的方法里面。 所以,嵌套的事务都不能生效。故调用ServiceC.method_c其实没有产生新事务,存储过程在显示执行commit时,直接提交了ServiceA.method_a的事务,后面无法再回滚。

          只有来自外部的方法调用才会被AOP代理捕捉,类内部方法调用类内部的其他方法,子方法并会不引起事务行为,即使被调用的方法上使用有@Transactional注解。
         类内部方法调用内部的其他方法,被调用的方法体中如果有try catch,则catch中必须用throw new Exception(),否则即使主方法上加上@Transactional注解,如果被调用的子方法出错也不会抛出异常,不会引起事务起作用。

解决方案

                   参考https://blog.youkuaiyun.com/xlgen157387/article/details/79026285

                          https://blog.youkuaiyun.com/m0_37701381/article/details/85066711

验证效果

                  项目中本来逻辑B的存储过程就是在另一个service类中实现的,属于调用外部方法

                  获取代理对象调用内嵌方法【报错aspectj-autoproxy 循环依赖报错has been injected into other beans】

                                                             【多个动态代理导致循环依赖报错问题解决

                  从上下文对象获取对象调用 【我的项目中无效】    

结论

           疑问暂未解决,待后续完善。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值