ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring嵌套事务机制

2020-11-15 19:01:50  阅读:133  来源: 互联网

标签:事务 调用 Spring 回滚 代理 嵌套 方法


之前写过一篇文章,是关于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就是这么实现的,个人理解就是为了避免引入不必要的复杂度,因为理论上动态代理也是可以代理protected方法的。

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

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

Spring事务相关的重要的知识点差不多就这些了。

标签:事务,调用,Spring,回滚,代理,嵌套,方法
来源: https://www.cnblogs.com/shen-smile/p/13977828.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有