事务嵌套问题_Spring嵌套事务机制

c06c9b9104630a93a46ae1ff6169ee0f.png

之前写过一篇文章,是关于Spring嵌套事务机制的,回过头来看发现有不少问题,但暂时不想删掉它,所以再写一篇文章更正一下之前的错误。这里先再次说明一下PROPAGATION_NESTED的作用,若当前存在事务则以嵌套事务方式执行,若不存在事务则创建一个新事务。

考虑到动态代理的实现方式,同一个类内部不同方法之间的调用只有外部方法的代理会生效,因此这里的讨论不考虑同一个类内部方法之间互相调用的情况,只考虑不同的类之间的方法进行调用的情况。

我们知道嵌套事务底层实际是利用SAVEPOINT实现的,因此外部事务回滚必然会导致整个事务回滚。若外部没有事务,则内部事务是否回滚取决于内部代码。这里假设调用方法叫ServiceA,被调用方法叫ServiceB。A上面标注的是PROPAGATION_REQUIRED,B上面标注的是PROPAGATION_NESTED。假设现在代码发生了异常,异常发生的位置存在三种情况:①发生在A处、②发生在B处、③两处都发生了异常。

若是情况①,内部事务包含在外部事务中,因此内外部的事务都会回滚。

若是情况②,还得再细分为两种情况,即A里面是否忽略B的异常,若A忽略B产生的异常,则内部事务回滚,外部事务正常提交。若A将B的异常继续往上抛出,则内外部事务都会回滚。

若是情况③,那自然不用多解释,内外部事务必然都会回滚。

可能出现的情况大概就这么几种,使用起来其实也不复杂,知道这几个小细节用起来就不会出错了。

再补充几点使用Spring事务的细节吧。之前做过一些实验,正好一起记录一下。主要有三点:使用声明式事务的注意事项、内部调用的事务生效情况、跨类调用的事务生效情况。

使用声明式事务时,无论是JDK动态代理,还是CGLIB动态代理,都只会为public方法生成事务,因此给非public方法加@Transactional注解是不生效的。Spring之所以这样实现,个人理解可能是为了避免引入不必要的复杂度,因为理论上动态代理也是可以代理非public方法的。

调用代理类中的非事务方法时,即使该方法内部调用了代理类中其他的事务方法,内部方法的事务也是不会生效的。因为Spring同时维护了目标对象和代理对象,不需要增强的方法Spring会直接走目标对象,所以这种方式下事务就不生效了。

跨类调用时,若外部方法未开启事务则外部方法中的数据不会回滚,内部方法则由该方法的事务配置决定。若外部方法开启事务,默认配置下内外部方法都会存在事务,除非自定义了事务传播属性。

Spring事务相关的重要一点的知识点差不多就这些了,时隔五个月我终于找回公众号的密码了哈哈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值