spring-事务之嵌套事物分析

一 非嵌套事务

如果是单事务的话,一般在方法上加上@Transactional注解就可以使改方法进行生效,使用也是比较简单的,但是如果牵涉到一个

方法里面调用了里一个服务里面的方法,且该方法上面也加上了@Transactional注解,这个时候,事物就可能不一定生效了,看下面的代码

ServiceA {  
             
         void methodA() {  
             ServiceB.methodB();  
         }  
        
    }  
        
ServiceB {  
             
         void methodB() {  
         }  
             
    }  

如果这个时候,methodB方法出现了异常,只会导致methodB方法进行回滚,但是methodA方法可能会正常被提交,也有可能会出现失败回滚,具体要分场景讨论

二 嵌套事务回滚机制

针对一个方法调用另一个方法,如果一个方法发生了事物回滚,会不会导致全局事物回滚,要看具体情况分析,下面就分析各种场景不同导致的结果不同

1 业务A的方法的事务级别为PROPAGATION_REQUIRED,业务B的方法的事务级别为PROPAGATION_REQUIRED

1、如果ServiceA.methodA已经起了事务,这时调用ServiceB.methodB,会共用同一个事务,如果出现异常,ServiceA.methodA和ServiceB.methodB作为一个整体都将一起回滚。

2、如果ServiceA.methodA没有事务,ServiceB.methodB就会为自己分配一个事务。ServiceA.methodA中是不受事务控制的。如果出现异常,ServiceB.methodB不会引起ServiceA.methodA的回滚。

2  业务A的方法的事务级别为PROPAGATION_REQUIRED,业务B的方法的事务级别为PROPAGATION_REQUIRED_NEW

1、如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。

2、如果ServiceB.methodB失败回滚,如果他抛出的异常被ServiceA.methodA的try..catch捕获并处理,ServiceA.methodA事务仍然可能提交;如果他抛出的异常未被ServiceA.methodA捕获处理,ServiceA.methodA事务将回滚。

3 业务A的方法的事务级别为PROPAGATION_REQUIRED,业务B的方法的事务级别为PROPAGATION_REQUIRED_NETESED

调用ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的子事务并设置savepoint

1、如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB也将回滚。

2、如果ServiceB.methodB失败回滚,如果他抛出的异常被ServiceA.methodA的try..catch捕获并处理,ServiceA.methodA事务仍然可能提交;如果他抛出的异常未被ServiceA.methodA捕获处理,ServiceA.methodA事务将回滚。

三 事务可能不生效以及注意解决方案

1 事务不生效的原因,一般对于单个事务可能是因为内部使用了try catch处理机制,导致事务失效,还有一种可能是基于使用了嵌套事务,配置不合理导致事务失效

2 事务生效的具体可能分析

第一种情况:同一个类中 一个方法无嵌套方法
如果方法名上加上@Transactional注解,方法内不要用try catch ;如果必须要用try catch ,则catch中必须用throw new RuntimeException()。否则事务不起作用。

第二种情况:同一个类中 方法A嵌套方法B
方法A有@Transactional,方法内都没有try catch,事务起作用。
方法A有@Transactional和try catch,并且catch中用throw new RuntimeException(),事务起作用。

第三种情况:不同类中,方法C嵌套方法B
方法B上加上@Transactional注解,方法内不要用try catch ;如果必须要用try catch ,则catch中必须用throw new RuntimeException()。否则方法B的事务不起作用。
方法C上加上@Transactional注解,方法内不要用try catch ;如果必须要用try catch ,则catch中必须用throw new RuntimeException(),此时方法B怎么写都行。否则方法C的事务不起作用。

3 总结,如果想确保事务生效,一般如果使用try...catch...处理机制的话,一定要throw相关异常,否则如果异常都被处理了,可能会导致事务不能回滚

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值