昨天帮助同事解决一个问题,其中遇到一个问题涉及到spring的事务,当时有点不敢肯定,做了实验,并参考了其他同仁的,做了些总结,希望能帮助到大家。
我们首先先来看下spring的事务的传播特性:
事务传播行为类型 |
说明 |
PROPAGATION_REQUIRED |
如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。 |
PROPAGATION_SUPPORTS |
支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY |
使用当前的事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NEW |
新建事务,如果当前存在事务,把当前事务挂起。 |
PROPAGATION_NOT_SUPPORTED |
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER |
以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED |
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
当使用PROPAGATION_NESTED时,底层的数据源必须基于JDBC 3.0,并且实现者需要支持保存点事务机制。
我们现在挨个来讲解下这个里面容易误解的几个:
1. PROPAGATION_REQUIRED
假设有下面代码:
ServiceA { /** * 事务属性配置为 PROPAGATION_REQUIRED */ void methodA() { try { ServiceB.methodB(); } catch(Exception e){ e.printstacktrace(); } } } ServiceB { /** * 事务属性配置为 PROPAGATION_REQUIRED */ void methodB() { } }
其实required从我面试候选人来看,基本上都能答出来,但是看到上面的情景是回滚还是提交,基本上答上来的很少,我们再来看下定义,如果当前没有事务,就开启一个,如果有就加入到这个事务里面,也就是说整个是一个事务,所以B发生异常,会导致整个事务一块回滚。从这个里面可以看到,简单的将methodB异常捕获,认为整个事务会提交,其实是不行的。
2. PROPAGATION_REQUIRES_NEW
ServiceA { /** * 事务属性配置为 PROPAGATION_REQUIRED */ void methodA() { try { ServiceB.methodB(); } catch(Exception e){ e.printstacktrace(); } } } ServiceB { /** * 事务属性配置为 PROPAGATION_REQUIRES_NEW */ void methodB() { } }requires new这种类型,基本上所有的人都能答正确,A和B是两个独立的事务,内外两个事务没有任何影响,结果是B回滚,A提交
3. PROPAGATION_REQUIRED
ServiceA { /** * 事务属性配置为 PROPAGATION_REQUIRED */ void methodA() { try { ServiceB.methodB(); } catch(Exception e){ e.printstacktrace(); } } } ServiceB { /** * 事务属性配置为 PROPAGATION_NESTED */ void methodB() { } }
从概念来看,有一个嵌套事务出现了
我们来分析下这个,首先我们先根据一个图将这个分解下:
(上图A、B、C、D代表几个时机,我们用AD和BC代表这两个事务,1,2,3代表事务执行的三个阶段)
嵌套事务达到的效果如下:
1. 事务BC与事务AD一起commit,即:作为事务AD的子事务,事务BC只有在事务AD成功commit时(阶段3成功)才commit。这个需求简单称之为“联合成功”
2. 事务BC的rollback不影响事务AD的commit
也就是说第一个是required的特性,第二个是requires new的特性
当BC事务成功commit时,PROPAGATION_NESTED的行为与PROPAGATION_REQUIRED一样。只有当事务AD在D点成功commit时,事务BC才真正commit,如果阶段3执行异常,导致事务AD rollback,事务BC也将一起rollback ,从而满足了“联合成功”
当阶段2执行异常,导致BC事务rollback时,因为设置了savePoint,AD事务可以选择与BC一起rollback或继续阶段3的执行并保留阶段1的执行结果,从而满足了“隔离失败”。
强调,补充一点:PROPAGATION_NESTED只是Spring针对JDBC3.0以上版本SavePoint机制的一个事务传播机制的扩展,J2EE体系中是没有的,所以如果应用中使用JTA作为底层的事务管理机制的话,使用Spring也是不可能支持PROPAGATION_NESTED。
相关推荐
通过代码解析spring传播特性,包括 1、Propagation.REQUIRED 方法被调用时自动开启事务,在事务范围内使用则使用同一个事务,否则开启新事务。 2、Propagation.REQUIRES_NEW 无论何时自身都会开启事务 3、...
事务传播特性&事务隔离级别 详细的事务传播特性&事务隔离级别
Spring事务的传播特性和隔离级别 事务的几种传播特性详细介绍
spring事务的传播特性和事务隔离级别
spring事务的传播特性.pptx
Spring控制Hibernate中的事务传播特性与隔离级别操作,通过利用spring和Hibernate的两个HibernateTemplate 和 jdbcTemplate类,实现数据的交互。
Java面试题54.Spring事务的传播特性和隔离级别.mp4
Spring 管理事务(传播特性、隔离级别、readonly).rar
java面试宝典
spring事务_案例_PPT 一、事务传播机制的demo案例,内容包括: 1.业务代码列举7种事务传播机制的情况,每个测试方法都附带日志分析记录、使用场景和实际场景,小白也能看得懂!!! 2.在测试类Test包下,使用juniter...
NULL 博文链接:https://zhouchaofei2010.iteye.com/blog/2397918
spring支持7种事务传播行为,确定客户端和被调用端的事务边界(说得通俗一点就是多个具有事务控制的service的相互调用时所形成的复杂的事务边界控制),这篇文章主要给大家介绍了关于Spring事务传播行为的相关资料,...
此外,Spring事务管理器支持多种类型的事务策略,包括不同的传播行为和隔离级别,允许开发者根据具体业务场景选择最合适的事务管理策略。深入理解Spring声明式事务的工作原理,不仅能帮助开发者更高效地使用Spring...
* 配置事务的传播特性 * 配置哪些类哪些方法使用事务 2.编写业务逻辑方法 * 继承HibernateDaoSupport类,使用this.HibernateTemplate这个类持久化数据 * HibernateTemplate是对session的轻量级的封装 * 默认...
上面我们只是简单的使用事务,这里将讨论Spring事务机制中最重要的两个配置项,即隔离级别与传播行为。毫无疑问本节内容是本章的核心内容,也是互联网企业最关注的内容之一,因此他十分重要,值得花费大的篇幅去讨论...
传播特性有几种?7种; 某一个事务嵌套另一个事务的时候怎么办? REQUIRED_NEW和REQUIRED区别 Spring的事务是如何回滚的,实现原理; 抽象类和接口的区别,什么时候用抽象类什么时候用接口; StringBuilder和...
事务本⾝并不存在什么传播特性,不要混淆事务本⾝和Spring的事务应⽤策略。(当然,找⼯作⾯试时,还是可以巧妙的描述传播 特性的) 2.⼀说到事务,⼈们可能⼜会想起create、begin、commit、rollback、close、...
SpringAOP入门和原理分析,动态代理
10.3.1 Spring事务传播机制回顾 10.3.2 相互嵌套的服务方法 10.4 多线程的困惑 10.4.1 Spring通过单实例化Bean简化多线程问题 10.4.2 启动独立线程调用事务方法 10.5 联合军种作战的混乱 10.5.1 Spring事务管理器的...
9.5.7. 事务传播 9.5.8. 通知事务操作 9.5.9. 结合AspectJ使用 @Transactional 9.6. 编程式事务管理 9.6.1. 使用TransactionTemplate 9.6.2. 使用PlatformTransactionManager 9.7. 选择编程式事务管理还是声明...