Spring事务传播属性介绍(一).required 和 reuqires_new
Mandatory、Never、Not_Support传播属性分析传送门:https://www.cnblogs.com/lvbinbin2yujie/p/10260030.html
Nested传播属性分析传送门:https://www.cnblogs.com/lvbinbin2yujie/p/10260066.html
我的Spring事务传播属性介绍比较传送门:https://files.cnblogs.com/files/lvbinbin2yujie/Spring_Tx_Note.rar
最近查看了Spring事务源码,是4.2.x的版本还是4.3.x的版本,简单了解了一些事务的概念,介绍下我对Spring事务源码的分析.
Spring一共七种事务传播属性,本文先来作为开篇介绍。
REQUIRED事务,Spring Transactional注解默认的事务,需要该方法在有事务情况下运行,如果当前没有事务就新建一个事物;
REQUIRES_NEW事务,当前方法运行没有事务,新建一个事物,当前方法有事务将当前事务挂起,新事物执行完毕再恢复原有事务;
这里提一点.,以前不明白什么是同一事务核心是什么,后来看到有位仁兄介绍,同一事务的事务信息、事务状态对象不同,但是底层是同一个Connection对象;这点我深以为.
实验说明环节
包结构:
Spring配置文件: (简单介绍下, 定义了一个数据源、DataSourceTransactionManager;此外tx:annotation-driven作用是用来启用Transactional注解的)
ServiceA.java文件
ServiceB.java文件
测试Main方法:
PROPAGATION_REQUIRED
说明: 默认的事务级别, 需要事务;如果当前没有事务,则创建新的事务;如果有事务呢,就加入当前的事务;
如果所有的Transactional标签都是默认的,REQUIRED时,方法里的提交、回滚都是一起的,要么所有都提交,要么所有都回滚;一荣俱荣,一损俱损;
查看源码时候打印事务的日志:
查看输出结果: 可以看到 确实提交了,并且加入了之前的事务,加入之前事务就是共用的一个Connection对象;
情景二: 修改ServiceB的addUser方法 来模拟调用其他业务方法时候执行抛出运行时异常; (同时将数据库之前测试结果 删除,便于观察)
先查看结果: 艾尼路记录添加进来又回退了, 查看日志:
说明: addUser抛出类型为RuntimeException类型的异常,callB捕获该异常之后,发现addUser在事物callB中,于是将事务状态DefaultTransactionStatus对戏中的事务对象DataSourceTransactionObject中的ConnectionHolder对象,即持有底层Connection的对象,将ConnectionHolder标记为rollbackOnly为true,然后将异常抛给调用addUser的callB方法;
在callB调用时根据Spring事务回滚规则,决定回滚操作;因为在情景二同一个事务中ConnectionHolder中持有的Connection对象是同一个,所以callB方法整个回滚了;
情景三: callB方法中手动try-catch来捕获异常会发生什么呢?
修改ServiceA的callB方法(为了便于观察,不输出异常,只是简单打印)
直接查看输出日志(最后一行抛出的异常排版原因未截全): 查看日志,记录确实添加了但是又回滚过了,数据库里没有记录。
异常信息:
Exception in thread "main" org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
说明: callB作为事务的开始,addUser作为事务的一部分,addUser抛出异常以后将ConnectionHolder对象的rollbackOnly设置为true,标记为需要回滚,但是执行完callB方法,没有抛出异常,就认为应该正常提交; 提交之前会校验两次,有一次是 Global transaction is marked as rollback-only but transactional code requested commit;
意思是全局事务需要回滚操作,但是事务代码现在要提交,这时候Spring还是会回滚;(通俗点就是addUser方法需要回滚,但是callB方法没有发生预料之外的异常,因为异常自己手动捕获,这时候Spring还是会回滚);
callB和ServiceB的事务信息对象TransactionInfo是不一样的,其属性事务状态TransactionStatus也不是同一个对象,TransactionStatus的底层事务对象transaction也不是同一个对象,transaction持有ConnectionHolder对象的Connection确实同一个,这样就保证了可以使用Connection对象来保持事务的一致性,一起提交、一起回滚; 保证两个Connection是同一个对象的是ThreadLocal,TransactionSynchronizationManager的resources里存放了着;
总结: REQUIRED不建议手动捕获异常,会破坏Spring的事务规则;try-catch需要结合传播类型,再决定使用与否;
PROPAGATION_REQUIRES_NEW
说明: 创建新的事务并执行,如果当前有事务,那将当前事务挂起,新建一个事物;
给ServiceA类callB方法修改下:
ServiceB类添加方法addUserFail,事务属性设置为REQUIRE_NEW
正常情况下查看输出日志:
可以发现,当进入REQUIRED_NEW事务里的方法时,挂起了原来的事务,事务执行完毕恢复了事务;并且外层事务和addUserFail事务是分别提交的;
情景三.
ServiceA方法:
ServiceB方法:
测试类方法:
说明:callB2方法调用了ServiceB的两个事务方法,ddUserSuccess方法是REQUIRED事务,addUserFail方法是REQUIRED_NEW事务,按照之前分析的,REQUIRED_NEW的方法是一个新的事务,那我抛出异常自己就会回滚,不应该干扰到callB2方法的回滚;
执行结果: addUserSuccess方法被带着一起回滚了,即外层事务也被带着一起回滚了;
查看源码发现: addUserFail的确新建了事务,然后抛出异常之后,着手回滚,回滚完成后将异常throw了,异常被throw那就会丢给调用addUserFail的地方,没错,丢到了callB2方法里,那callB2也着火了,发生异常,这时候callB2的事务也被认定为执行失败应当回滚,那callB2的事务就开始回滚,callB2内部事务addUserSuccess回滚, 所以一条记录都没有写进去.
(想了下,REQUIRED_NEW事务的方法就在调用他的地方手动捕获异常,不让异常向上传递了,这样就能达到目的,且不会像REQUIRED一样报异常)
简单画了如下例子,外层事务为REQUIRED类型;外层事务有两个方法,A、B;Spring默认回滚规则为RuntimeException或Error类型,下面例子抛出异常也是RumtimeException或Error类型,且没有手动try-catch捕获异常;
Spring事务传播属性介绍(一).required 和 reuqires_new的更多相关文章
- Spring事务传播属性介绍(二).mandatory、not_supported、never、supports
Required.Required_New传播属性分析传送门:https://www.cnblogs.com/lvbinbin2yujie/p/10259897.html Nested传播属性分析传送 ...
- Spring事务传播属性介绍(三).Nested
Required.Required_New传播属性分析传送门:https://www.cnblogs.com/lvbinbin2yujie/p/10259897.html Mandatory.Neve ...
- spring事务传播机制实例讲解
http://kingj.iteye.com/blog/1680350 spring事务传播机制实例讲解 博客分类: spring java历险 天温习spring的事务处理机制,总结 ...
- Spring事务传播机制和数据库隔离级别
Spring事务传播机制和数据库隔离级别 转载 2010年06月26日 10:52:00 标签: spring / 数据库 / exception / token / transactions / s ...
- spring 事务传播机制
spring 事务 传播机制 描述的 事务方法直接相互调用,父子事物开启,挂起,回滚 等的处理方式. 绿色的 那几个 我认为比较重要. 1 , @Transactional(propagation=P ...
- spring 事务传播行为实例分析
Spring事务传播行为: spring特有的事务传播行为,spring支持7种事务传播行为,确定客户端和被调用端的事务边界(说得通俗一点就是多个具有事务控制的service的相互调用时所形成的复杂的 ...
- Spring事务传播机制与隔离级别(转)
Spring事务传播机制与隔离级别 博客分类: Spring 转自:http://blog.csdn.net/edward0830ly/article/details/7569954 (写的不错) ...
- Spring 事务传播行为的使用
...
- spring事务传播特性实验(2):PROPAGATION_REQUIRED实验结果与分析
本文延续上一文章(spring事务传播特性实验(1):数据准备),在已经准备好环境的情况下,做如下的实验,以验证spring传播特性,加深对spring传播特性的理解. 本次主要验证PROPAGATI ...
随机推荐
- Uval4726-数形结合的思想
题意:给定一段01序列,求一段长度不小于L的连续序列,使其平均值最大 思路:一看就想到了斜率优化,但是用基本的推公示一直没推出来,看了别人的代码,像推出斜率的式子一直没弄出来..后来一看别人写的题解, ...
- 3.Ubuntu下安装mysql并在windows下使用Navicat来连接
一.安装mysql(只需要三条命令) 1.第一条命令(中间需要输入root用户密码): sudo apt-get install mysql-server 2.第二条命令: sudo apt-get ...
- [ASE][Daily Scrum]11.12
这几天Jiafan同学回学校去了,服务器的问题暂时未解决.继续搭建服务器中: View Shilin Liu 修复tank的错位问题 产生残缺地图 Client Jiafan Zhu( ...
- 用光的微粒说和广义相对论来解释衍射现象 Explanation of Diffraction Phenomenon by Particle Theory of Light and General Relativity
历史上,物理学是用波动说来解释光的衍射现象.但用微粒说结合广义相对论同样可以做到. 把光看作粒子,当经过障碍物边缘时,由于广义相对论效应,边缘附近的空间被弯曲,使得不同路径的平行光发生偏转,落在障碍物 ...
- OpencvSharp 在WPF的Image控件中显示图像
1.安装OpencvSharp 我使用的是VS2013 社区版,安装OpencvSharp3.0 在线安装方法:进入Tools,打开NuGet的包管理器 搜索Opencv 安装之后就可以使用,无需再做 ...
- .net图表之ECharts随笔02-字符云
后续每一类图表,若无特殊说明,都将建立在01的基础上,修改参数option,且参数均以json的格式 要形成如图所示的字符云,一般需要设置两个大参数——title和series 其中,title就是图 ...
- asp.net mvc+httpclient+asp.net mvc api入门篇
第一步:创建一个ASP.NET MVC API项目 第二步:在api项目里面创建一个类 public class Student { public int Id { get; set; } publi ...
- UWP 多语言的三个概念
首先了解一下 RFC4646 和 BCP-47 是什么东西: RFC4646 The name is a combination of an ISO 639 two-letter lowercase ...
- 使用jQuery实现一个类似GridView的编辑,更新,取消和删除的功能
先来看看下面实时效果演示: 用户点击编辑时,在点击行下动态产生一行.编辑铵钮变为disabled.新产生的一行有更新和取消的铵钮,点击“取消”铵钮,删除刚刚动态产生的行.编辑铵钮状态恢复. 更新与删除 ...
- 201621123018《java程序设计》第12周作业总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 面向系统综合设计-图书馆管理系统或购物车 使用流与文件改造你的图书馆管理系统或购物车. 2.1 简述如何 ...