spring交易声明的几个传播特性
近期遇到了一个spring事务导致的问题,所以写了几个小程序了解了一下事务的传播特性,以下分别举样例分别看看事务的传播特性。
事务的几种传播特性
1. PROPAGATION_REQUIRED: 假设存在一个事务,则支持当前事务。
假设没有事务则开启
- /**
- * TransactionTestService test1和test2配有事务(PROPAGATION_REQUIRED) */
- public interface TransactionTestService {
- //事务属性 PROPAGATION_REQUIRED
- public void test1() throws Exception{
- avInfoTaskTunnel.insertAvInfoTask();
- test2();
- }
- //事务属性 PROPAGATION_REQUIRED
- public void test2() throws Exception{
- avRequestTunnel.insertAvRequest();
- throw new Exception();
- }
- }
- /**
- * main
- */
- public class TransactionTestMain {
- public static void main(String[] args) throws Exception{
- TransactionTestService transactionTestService = (TransactionTestService)context.getBean("transactionTestService");
- try {
- transactionTestService.test1();
- } catch (Exception e) {
- }
- }
- }
上述代码中test1()和test2()都配有PROPAGATION_REQUIRED事务属性,test1()内部调用test2(),这样test1()和test2()方法将都处于同一事务之中,当在test2()中抛出异常。会导致test1()和test2()方法中的事务都回滚。
可是,假设test1()方法对调用test2()时捕获异常,结果会是如何的呢? test1应该能正常写入没问题,那么test2呢?
- //test1()中捕获test2()抛出的异常
- public void test1() throws Exception{
- avInfoTaskTunnel.insertAvInfoTask();
- try {
- test2();
- }catch (Exception e) {
- }
- }
最后的结果test2()也将会正常的写入。
事实上,上面情况中假设仅仅是test1()配有PROPAGATION_REQUIRED事务属性。test2()不配置不论什么事务属性。发生的结果也是一致的。上面的情形相当于:
- public static void main(String[] args) throws Exception{
- Connection con = null;
- try {
- con=getConnection();
- con.setAutoCommit(false);
- transactionTestService.test1(); //test1()和test2()处于同一事务之中
- con.commit();
- } catch (Exception e) {
- con.rollback();
- } finally {
- closeCon();
- }
- }
上述test1()和test2()是同一个类的两个方法,那么要是它们处于不同类呢?
- //main函数不变,test1()中调用test2()地方换成调用还有一个类中配有PROPAGATION_REQUIRED事务属性的方法
- //不正确otherService.test2()捕获异常的情形就不是必需说了。必然都回滚。
- public void test1() throws Exception{
- avInfoTaskTunnel.insertAvInfoTask();
- try {
- otherService.test2(); //PROPAGATION_REQUIRED事务属性
- } catch (Exception e) {
- }
- }
- //otherService.test2()
- public void test2() throws Exception{
- avRequestTunnel.insertAvRequest();
- throw new Exception();
- }
上述相同捕获了异常,可是结果会如何呢? 结果有点出乎意料。与之前test1(),test2()处于同一类的情形不同,这个时候。两个方法都将回滚。而且在调用test1()的地方会抛出以下异常。
这是因为子事务在回滚的时候已经将主事务标记成了rollback-only,这样导致主事务在提交的时候就会抛出以下这个异常。
另外:假设otherService.test2()没有配置不论什么事务属性,那么test2()抛出异常的时候,将导致test1()和test2()都回滚。
- org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
上述情况网上查询到一种解决方案是在transactionManager中将globalRollbackOnParticipationFailure 设置为 q=false&ie=utf-8&src=se_lighten" style="color:rgb(16,138,198)">false
- <bean id="transactionManager"
- class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource">
- <ref local="dataSource" />
- </property>
- <property name="globalRollbackOnParticipationFailure" value="false" />
- </bean>
2. PROPAGATION_SUPPORTS: 假设存在一个事务,支持当前事务。假设没有事务,则非事务的运行
- //TransactionTestService test1()配有事务(PROPAGATION_SUPPORTS)
- public void test1() throws Exception{
- avInfoTaskTunnel.insertAvInfoTask();
- throw new Exception();
- }
- /**
- * main
- */
- public class TransactionTestMain {
- public static void main(String[] args) throws Exception{
- TransactionTestService transactionTestService = (TransactionTestService)context.getBean("transactionTestService");
- try {
- transactionTestService.test1();
- } catch (Exception e) {
- }
- }
- }
TransactionTestService的test1()配有PROPAGATION_SUPPORTS事务属性,我们知道这样的情形下假设配的是PROPAGATION_REQUIRED事务属性。那么test1()将新建事务执行。可是PROPAGATION_SUPPORTS属性不会新建,这样的情形下,test1()方法将正常提交。那假设是外层事务配有事务呢?例如以下所看到的,此种情形test2()将处于事务之中了。
- //PROPAGATION_REQUIRED事务属性
- public void test1() throws Exception{
- avInfoTaskTunnel.insertAvInfoTask();
- test2();
- }
- //PROPAGATION_SUPPORTS事务属性
- public void test2() throws Exception{
- avRequestTunnel.insertAvRequest();
- throw new Exception();
- }
3. PROPAGATION_MANDATORY: 假设已经存在一个事务,支持当前事务。假设没有一个活动的事务。则抛出异常。
- //情形1:PROPAGATION_REQUIRED事务属性 情形2:不配不论什么事务属性
- public void test1() throws Exception{
- avInfoTaskTunnel.insertAvInfoTask();
- otherService.test2();
- }
- //otherService的test2()配置PROPAGATION_MANDATORY事务属性
- public void test2() throws Exception {
- avRequestTunnel.insertAvRequest();
- throw new Exception();
- }
- //test1()处于情形2时抛出异常,test2()不可以提交,可是test1()却是可以成功提交的
- org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
上述情况,当test1()处于情形1时,会是的test1()和test2()都处于事务其中;test1()处于情形2时,就会抛异常,可是这个时候test2()不可以提交,可是test1()却是可以成功提交的。此外,另一点,注意上述test2()是处于另一个类中的,假设是处于同一个类。那么PROPAGATION_MANDATORY不会由于外层是否有事务而抛异常。
4. PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务。假设一个事务已经存在,则将这个存在的事务挂起。
- //情形1:PROPAGATION_REQUIRED事务属性 情形2:不配不论什么事务属性
- public void test1() throws Exception{
- avInfoTaskTunnel.insertAvInfoTask();
- otherService.test2();
- }
- //otherService的test2()配置PROPAGATION_REQUIRES_NEW事务属性
- public void test2() throws Exception {
- avRequestTunnel.insertAvRequest();
- throw new Exception();
- }
上述情况,test1()处于情形2时test2()新建事务。这点没有问题。那假设test1()处于情形1呢?也就是说test1()已经有事务了。结果是test2()处于新的事务中,怎么确定是处于新的事务中呢?看以下代码:
- //test1配置PROPAGATION_REQUIRED事务属性
- public void test1() throws Exception{
- avInfoTaskTunnel.insertAvInfoTask();
- otherService.test2(); //PROPAGATION_REQUIRES_NEW事务属性
- }
- //otherService.test2()
- public void test2() throws Exception{
- avRequestTunnel.insertAvRequest();
- throw new Exception();
- }
假设是在同一事务中。那么情形将同于讲述PROPAGATION_REQUIRED属性时的情形。test1()和test2()都将回滚,而且抛出异常事务被打上rollback-only标记的异常。可是这里,结果就是test2()回滚,test1正常提交,所以otherService.test2()处于新的事务中。注意:上述情况test2()也是还有一个类的方法,假设属于同一类,也就是test1()和test2()处于同一个类。test1()中调用test2(),那么配置的PROPAGATION_REQUIRES_NEW将无效(跟test2()什么事务属性都没配置一样)。
可是假设是main函数中直接调用test2(),那么还是会起一个新的事务。
第二种证明test1()和test2()处于不同事务的方式是,在test2()不抛出异常,然后再test1()调用了test2()之后,抛出异常,最后结果是()回滚。test2()正常提交。
5. PROPAGATION_NOT_SUPPORTED: 总是非事务地运行,并挂起不论什么存在的事务。
- //test1配置PROPAGATION_REQUIRED事务属性
- public void test1() throws Exception{
- avInfoTaskTunnel.insertAvInfoTask();
- otherService.test2(); //PROPAGATION_NOT_SUPPORTED事务属性
- }
- //otherService.test2()
- public void test2() throws Exception{
- avRequestTunnel.insertAvRequest();
- throw new Exception();
- }
假设otherService.test2() 没有配置事务属性,那么test2()抛出异常时,test1()和test2()都回滚。可是如今test2()配置了PROPAGATION_NOT_SUPPORTED事务属性,那么test2()将以非事务执行,而test1()继续执行在事务中。也就是说,此时,test1()回滚,test2()正常提交。
注意:假设test1()和test2()在同一类中。那么test2()的PROPAGATION_NOT_SUPPORTED失效。
6. PROPAGATION_NEVER: 总是非事务地运行。假设存在一个活动事务,则抛出异常
- //test1配置PROPAGATION_REQUIRED事务属性
- public void test1() throws Exception{
- avInfoTaskTunnel.insertAvInfoTask();
- otherService.test2(); //PROPAGATION_NEVER事务属性
- }
- //otherService.test2()
- public void test2() throws Exception{
- avRequestTunnel.insertAvRequest();
- throw new Exception();
- }
- //test1()配置PROPAGATION_REQUIRED事务属性, otherService.test2()配置PROPAGATION_NEVER事务属性,将抛以下异常:
- org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'
当然上述情况。假设是test1()和test2()在同一类中。那么PROPAGATION_NEVER也将失效。
7. PROPAGATION_NESTED:假设一个活动的事务存在,则执行在一个嵌套的事务中. 假设没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行
最easy弄混淆的事实上是 PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED。
PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 "内部" 事务. 这个事务将被全然 commited 或 rolled back 而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等. 当内部事务開始运行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续运行。还有一方面, PROPAGATION_NESTED 開始一个 "嵌套的"
事务, 它是已经存在事务的一个真正的子事务. 嵌套事务開始运行时, 它将取得一个 savepoint. 假设这个嵌套事务失败, 我们将回滚到此 savepoint.。嵌套事务是外部事务的一部分, 仅仅有外部事务结束后它才会被提交。
由此可见, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大差别在于, PROPAGATION_REQUIRES_NEW 全然是一个新的事务, 而 PROPAGATION_NESTED 则是外部事务的子事务, 假设外部事务 commit,
潜套事务也会被 commit, 这个规则相同适用于 roll back.
- //test1配置PROPAGATION_REQUIRED事务属性
- public void test1() throws Exception{
- avInfoTaskTunnel.insertAvInfoTask();
- otherService.test2(); //PROPAGATION_NESTED事务属性
- }
- //otherService.test2()
- public void test2() throws Exception{
- avRequestTunnel.insertAvRequest();
- }
上述情况。假设otherService.test2()配置PROPAGATION_REQUIRES_NEW事务属性。这样test1()回滚,可是test2()正常提交,由于这是两个事务。可是假设otherService.test2()配置PROPAGATION_NESTED事务属性。然后test1()和test2()将回滚。
版权声明:本文博客原创文章,博客,未经同意,不得转载。
spring交易声明的几个传播特性的更多相关文章
- 玩转Spring全家桶笔记 04 Spring的事务抽象、事务传播特性、编程式事务、申明式事务
1.Spring 的事务抽象 Spring提供了一致的事务模型 JDBC/Hibernate/Mybatis 操作数据 DataSource/JTA 事务 2.事务抽象的核心接口 PlatformTr ...
- spring 事务传播特性 和隔离级别
事务的几种传播特性1. PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务.如果没有事务则开启2. PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务 ...
- Spring事务的传播特性和隔离级别
事务的几种传播特性1. PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务.如果没有事务则开启2. PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务 ...
- Spring事务传播特性的浅析——事务方法嵌套调用的迷茫
Spring事务传播机制回顾 Spring事务一个被讹传很广说法是:一个事务方法不应该调用另一个事务方法,否则将产生两个事务.结果造成开发人员在设计事务方法时束手束脚,生怕一不小心就踩到地雷. 其实这 ...
- Spring各种传播特性源码实现的概览
这几天都在分析Spring的源码实现,看到事务管理的部分 我们知道事务的传播特性有下面几种,我标黄的就是最常用的3中传播特性, Sping在发生事务嵌套的时候,会依据内层事务的传播特性,来决定内层是事 ...
- 什么是事务?事务特性?事务隔离级别?spring事务传播特性?
一.事务的概述 什么是事务? 在数据库中,所谓事务是指一组逻辑操作单元即一组sql语句,当这个单元中的一部分操作失败,整个事务回滚,只有全部正确才完成提交.判断事务是否配置成功的关键点在于出现异常时事 ...
- 事务、事务特性、事务隔离级别、spring事务传播特性
事务.事务特性.事务隔离级别.spring事务传播特性 1.什么是事务: 事务是程序中一系列严密的操作,所有操作执行必须成功完成,否则在每个操作所做的更改将会被撤销,这也是事务的原子性(要么成功, ...
- 什么是事务、事务特性、事务隔离级别、spring事务传播特性
1.什么是事务: 事务是程序中一系列严密的操作,所有操作执行必须成功完成,否则在每个操作所做的更改将会被撤销,这也是事务的原子性(要么成功,要么失败). 2.事务特性: 事务特性分为四个:原子性(At ...
- Spring 事物传播特性
Spring 事物传播特性 这是Spring官方的定义 一共有7种 摘自源码省略了一部分 public interface TransactionDefinition { int PROPAGATIO ...
随机推荐
- Windows Phone开发(39):漫谈关键帧动画上篇
原文:Windows Phone开发(39):漫谈关键帧动画上篇 尽管前面介绍的几种动画会让觉得很好玩了,但是,不知道你是否发现,在前面说到的一系列XXXAnimation中,都有一个共同点,那就是仅 ...
- IOSi科研OS7
具体的使用说明的适应
新近.我进行了项目iOS7适应,它有没有用7.0SDK它是由于老project采用iOS7.0存在一些问题,以这个机会,我专门整理改编iOS7需要注意的几个地方. 记录,如下面: 一,iOS7 ...
- 当执行游戏0xc000007b错误的解决方法
如图,这个错误使无数玩家烦恼. 出现这个错误,可能是硬件的问题,也可能是软件的问题.可是,因为硬件引起该问题的概率非常小,而且除了更换硬件之外没有更好的解决方法,因此本文将具体介绍怎样通过软件解决此问 ...
- 网站上flv,MP4等格式的视频文件播放不出来的解决办法
在做一个网站时,发现视频文件,比如flv,MP4格式在本地可以正常的播放,但是传到了开发机器上,就不行了.播放器的文件地址是对的,就是一直没有反应. 经过长时间的实验,发现问题在与iis的设置问题.i ...
- ASP.NET 应用程序生命周期
1.请求到达IIS服务器,IIS根据文件后缀找到对应的ISAPI(Internet Server API)扩展来处理,这个配置可在网站属性里的“根目录”选项卡中的“配置”里看到.可以看到,ashx.a ...
- Ubuntu常用软件推荐,图文详细说明及下载
抛开Windows,其实在任何一款Linux发行版本中,我们都有超级大量的软件来安装,使用.这次的教程,我就以Ubuntu为例,来给大家推荐一些我认为不错的软件 声明: 1.本文提到的全部软件,都在文 ...
- Android源代码同步脚本(增加设置线程参数)
#!/bin/sh #Filename: repo_sync.sh count= ret= ] do #输入参数1,用作同步的线程数 #如果什么参数都不输入,默认线程为4 #usage: ./repo ...
- android应用开发--------------看RadioGroup源代码,写相似单选选项卡的集成控件(如底部导航,tab等等)
博客为 有时个哥 原创.如需转载请标明出处:http://blog.csdn.net/ls703/article/details/46694967 watermark/2/text/aHR0cDovL ...
- 懒人模式Singleton模式Meyers版本号
直接看代码: /* Singleton模式保证:在一个程序,,一个类有且只有一个实例.并提供一个访问 它的全局访问点 在编程其中.很多情况下,需要确保有一类的一个实例 比如: windopws系统中仅 ...
- POJ 3684 Priest John's Busiest Day 2-SAT+输出路径
强连通算法推断是否满足2-sat,然后反向建图,拓扑排序+染色. 一种选择是从 起点開始,还有一种是终点-持续时间那个点 開始. 若2个婚礼的某2种时间线段相交,则有矛盾,建边. easy出错的地方就 ...