一、PROPAGATION_NESTED
结合http://www.iteye.com/topic/35907,简单总结一下自己的理解:
(上图AD和BC代表两个事务,1,2,3代表事务执行的三个阶段。图简陋了点,有点像“金箍棒”)
使用嵌套事务的场景有两点需求:
- 需要事务BC与事务AD一起commit,即:作为事务AD的子事务,事务BC只有在事务AD成功commit时(阶段3成功)才commit。这个需求简单称之为“联合成功”。这一点PROPAGATION_REQUIRED可以做到。
- 需要事务BC的rollback不(无条件的)影响事务AD的commit。这个需求简单称之为“隔离失败”。这一点PROPAGATION_REQUIRES_NEW可以做到。
使用PROPAGATION_REQUIRED满足需求1,但子事务BC的rollback会无条件地使父事务AD也rollback,不能满足需求2。
使用PROPAGATION_REQUIRES_NEW满足需求2,但子事务(这时不应该称之为子事务)BC是完全新的事务上下文,父事务(这时也不应该称之为父事务)AD的成功与否完全不影响BC的提交,不能满足需求1。
同时满足上述两条需求就要用到PROPAGATION_NESTED了。PROPAGATION_NESTED在事务AD执行到B点时,设置了savePoint(关键)。
当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的执行结果,从而满足了“隔离失败”。
当然,要明确一点,事务传播策略的定义是在声明或事务管理范围内的(首先是在EJB CMT规范中定义,Spring事务框架补充了PROPAGATION_NESTED),编程式的事务管理不存在事务传播的问题。
另外,SavePoint在JDBC3.0中,所以应用嵌套事务必须保证JDK1.4+和驱动对JDBC3.0的支持。
强调,补充一点:PROPAGATION_NESTED只是Spring针对JDBC3.0以上版本SavePoint机制的一个事务传播机制的扩展,J2EE体系中是没有的,所以如果应用中使用JTA作为底层的事务管理机制的话,使用Spring也是不可能支持PROPAGATION_NESTED。不过JPA的体系中好像是有SavePoint的机制(还没有细研究过),Spring应该可以在之上做相应的支持。这点有待进一步研究!
二、PROPAGATION_REQUIRES_NEW
通常使用Spring框架的程序会统一的在Service层运用Spring AOP进行事务控制,分为声明式和编程式两种,互联网上已经有很多的资源介绍Spring事务的配置,Spring Reference也有详细介绍。但是介绍嵌套式事务的并不多。日前本人试图运用AOP记录Service的调用情况并记录到Database,但是发现当Service发生异常时无法正常记录Database log,后来通过为日志服务配置不同的事务策略才解决该问题,本文介绍一下嵌套式事务以及如何为不同的service配置不同的事务策略。
嵌套事务是指AService和BService都配置了事务,但是AService调用了BService的情况。此时BService是用AService的事务呢,还是新开一个自己的事务? Spring配置事务的时候有一个可选的参数propagation,默认为REQUIRED。使用这种策略时BService将使用Aservice的事务。
不管业务逻辑的service是否有异常,Log Service都应该能够记录成功,通常有异常的调用更是用户关心的。Log Service如果沿用业务逻辑Service的事务的话在抛出异常时将没有办法记录日志(事实上是回滚了)。所以希望Log Service能够有独立的事务。日志和普通的服务应该具有不同的策略。先贴上Spring 配置文件transaction.xml:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
- <!-- configure transaction -->
- <tx:advice id="defaultTxAdvice" transaction-manager="transactionManager">
- <tx:attributes>
- <tx:method name="get*" read-only="true" />
- <tx:method name="query*" read-only="true" />
- <tx:method name="find*" read-only="true" />
- <tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
- </tx:attributes>
- </tx:advice>
- <tx:advice id="logTxAdvice" transaction-manager="transactionManager">
- <tx:attributes>
- <tx:method name="get*" read-only="true" />
- <tx:method name="query*" read-only="true" />
- <tx:method name="find*" read-only="true" />
- <tx:method name="*" propagation="REQUIRES_NEW"
- rollback-for="java.lang.Exception" />
- </tx:attributes>
- </tx:advice>
- <aop:config>
- <aop:pointcut id="defaultOperation"
- expression="@within(com.homent.util.DefaultTransaction)" />
- <aop:pointcut id="logServiceOperation"
- expression="execution(* com.homent.service.LogService.*(..))" />
- <aop:advisor advice-ref="defaultTxAdvice" pointcut-ref="defaultOperation" />
- <aop:advisor advice-ref="logTxAdvice" pointcut-ref="logServiceOperation" />
- </aop:config>
- </beans>
如上面的Spring配置文件所示,日志服务的事务策略配置为propagation="REQUIRES_NEW",告诉Spring不管上下文是否有事务,Log Service被调用时都要求一个完全新的只属于Log Service自己的事务。通过该事务策略,Log Service可以独立的记录日志信息,不再受到业务逻辑事务的干扰。
相关推荐
本章将详细探讨Spring4中的切面事务处理、事物通知以及传播行为。 一、切面编程(AOP) 切面编程是Spring框架的一大特色,它允许开发者将关注点如日志记录、事务管理等从主业务逻辑中分离出来,形成独立的模块,即...
当我们遇到"AOP实现自我调用的事物嵌套问题"时,这通常涉及到Spring框架中的事务管理,特别是自调用方法在事务处理时可能会引发的问题。 首先,让我们理解Spring AOP的事务管理是如何工作的。Spring使用代理模式来...
本文将深入探讨“Spring事物传播测试表”所涉及的知识点。 首先,理解事务是非常重要的。在数据库操作中,事务确保数据的一致性和完整性。例如,一组相关的数据库操作要么全部成功,要么全部失败,这就是事务的ACID...
- `NESTED`:如果当前存在事务,则在嵌套事务内运行;如果没有事务,则行为类似于`REQUIRED`。 Spring事务管理的隔离级别包括: - `DEFAULT`:使用数据库的默认隔离级别。 - `READ_UNCOMMITTED`:最低隔离级别,...
Spring 事务管理是Java开发中一个至关重要的概念,特别是在企业级应用中,它确保了数据的一致性和完整性。Spring 提供了一种灵活的方式来管理和控制事务的边界,这主要体现在TransactionDefinition接口定义的7种事务...
### Spring事务的七大传播行为 在深入探讨Spring框架下的事务管理之前,我们首先明确事务的概念。事务是指一组操作作为一个整体,要么全部成功,要么全部失败。Spring提供了多种方式来管理和控制事务,其中一种重要...
- NESTED:如果当前存在事务,则创建一个嵌套事务;如果没有事务,则按照REQUIRED行为处理。 理解这些传播行为有助于在多层方法调用中正确地管理事务边界,确保事务的正确性和一致性。 综上所述,Spring 事务管理...
- NESTED:如果当前存在事务,则在嵌套事务内执行;如果不存在,则按REQUIRED行为执行。 2. 事务的隔离级别: 隔离级别用于解决并发控制中可能出现的问题,如脏读、不可重复读和幻读。Spring支持四种隔离级别: ...
- 描述:如果当前存在事务,则在嵌套事务内执行;如果当前不存在事务,则执行与 `PROPAGATION_REQUIRED` 类似的操作。 - 应用场景:适用于需要在现有事务中开启新事务的场景,比如日志记录等。 #### 二、Spring ...
- NESTED:如果当前存在事务,则在嵌套事务内执行;如果不存在,则按REQUIRED方式执行。 6. **事务的隔离级别** - READ_UNCOMMITTED:最低隔离级别,允许脏读、不可重复读和幻读。 - READ_COMMITTED:防止脏读,...
- `NESTED`:如果存在事务,则在嵌套事务内运行;若无事务,则行为类似于`REQUIRED`。 4. **事务的隔离级别** - `DEFAULT`:使用数据库默认的隔离级别。 - `READ_UNCOMMITTED`:最低级别,允许读取未提交的数据...
4. requires_new:如果当前有事务,则挂起该事物,并且自己创建一个新的事务给自己使用;如果当前没有事务,则跟required一样。例如,铃铛有饭吃,我看不上,不要,我自己买着自己吃。 5. not_supported:如果当前...
6. **事务嵌套**:在同一个事务中调用另一个@Transactional方法,Spring会处理这种事务嵌套。默认情况下,子事务将继承父事务的隔离级别和传播行为。 7. **事物边界**:理解事务边界是确保事务正确性的关键。事务...
7. **PROPAGATION_NESTED**:如果当前存在事务,则在嵌套事务内执行;如果不存在,则行为类似于PROPAGATION_REQUIRED。 事务隔离级别的选择和事务传播行为的设定,对于确保数据一致性至关重要。例如,如果你的应用...
Spring 中事务传播行为的介绍 Spring 中事务传播行为是指在分布式事务系统中,事务的边界定义和传播规则。在 Spring 框架中,定义了 7 种不同的传播行为,每种行为都有其特点和应用场景。 1. PROPAGATION_...
然而,这种方式容易引入编码陷阱,如事务环境问题,即在事务边界内调用其他事务边界内的方法,可能会导致事务嵌套或事务泄漏等问题。 ### 声明式事务模型 相比之下,声明式事务管理通过配置元数据(如注解或XML...
**问题十四:介绍一下Spring的事物管理** - **编程式事务管理**:通过编程的方式控制事务的开始、提交或回滚。 - **声明式事务管理**:通过配置文件或注解的方式声明事务的边界。 **问题十五:解释一下SpringAOP...
7. **PROPAGATION_NESTED**:如果当前存在事务,则在嵌套事务内运行;如果没有事务,则行为类似于PROPAGATION_REQUIRED。 在Hibernate中,事务管理通常通过Session接口进行,包括beginTransaction()、commit()和...