`
dsj177
  • 浏览: 510 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

spring 事务传播属性解析

阅读更多
Spring中事务的定义:
一、Propagation :
  key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。有以下选项可供使用:
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。

很多人看到事务的传播行为属性都不甚了解,我昨晚看了j2ee without ejb的时候,看到这里也不了解,甚至重新翻起数据库系统的教材书,但是也没有找到对这个的分析。今天搜索,找到一篇极好的分析文章,虽然这篇文章是重点分析PROPAGATION_REQUIRED 和 PROPAGATION_REQUIRED_NESTED的
解惑 spring 嵌套事务
/**
* @author 王政
* @date 2006-11-24
* @note 转载自http://www.iteye.com/topic/35907?page=1
*/
********TransactionDefinition 接口定义*******************
/**  
      * Support a current transaction, create a new one if none exists.  
      * Analogous to EJB transaction attribute of the same name.  
      *
This is typically the default setting of a transaction definition.  
      */  
     int PROPAGATION_REQUIRED = 0;  
 
     /**  
      * Support a current transaction, execute non-transactionally if none exists.  
      * Analogous to EJB transaction attribute of the same name.  
      *

Note: For transaction managers with transaction synchronization,  
      * PROPAGATION_SUPPORTS is slightly different from no transaction at all,  
      * as it defines a transaction scopp that synchronization will apply for.  
      * As a consequence, the same resources (JDBC Connection, Hibernate Session, etc)  
      * will be shared for the entire specified scope. Note that this depends on  
      * the actual synchronization configuration of the transaction manager.  
      * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization  
      */  
     int PROPAGATION_SUPPORTS = 1;  
 
     /**  
      * Support a current transaction, throw an exception if none exists.  
      * Analogous to EJB transaction attribute of the same name.  
      */  
     int PROPAGATION_MANDATORY = 2;  
 
     /**  
      * Create a new transaction, suspend the current transaction if one exists.  
      * Analogous to EJB transaction attribute of the same name.  
      *

Note: Actual transaction suspension will not work on out-of-the-box  
      * on all transaction managers. This in particular applies to JtaTransactionManager,  
      * which requires the javax.transaction.TransactionManager to be  
      * made available it to it (which is server-specific in standard J2EE).  
      * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager  
      */  
     int PROPAGATION_REQUIRES_NEW = 3;  
 
     /**  
      * Execute non-transactionally, suspend the current transaction if one exists.  
      * Analogous to EJB transaction attribute of the same name.  
      *

Note: Actual transaction suspension will not work on out-of-the-box  
      * on all transaction managers. This in particular applies to JtaTransactionManager,  
      * which requires the javax.transaction.TransactionManager to be  
      * made available it to it (which is server-specific in standard J2EE).  
      * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager  
      */  
     int PROPAGATION_NOT_SUPPORTED = 4;  
 
     /**  
      * Execute non-transactionally, throw an exception if a transaction exists.  
      * Analogous to EJB transaction attribute of the same name.  
      */  
     int PROPAGATION_NEVER = 5;  
 
     /**  
      * Execute within a nested transaction if a current transaction exists,  
      * behave like PROPAGATION_REQUIRED else. There is no analogous feature in EJB.  
      *

Note: Actual creation of a nested transaction will only work on specific  
      * transaction managers. Out of the box, this only applies to the JDBC  
      * DataSourceTransactionManager when working on a JDBC 3.0 driver.  
      * Some JTA providers might support nested transactions as well.  
      * @see org.springframework.jdbc.datasource.DataSourceTransactionManager  
      */  
     int PROPAGATION_NESTED = 6;  


*************************************************************************
在这篇文章里,他用两个嵌套的例子辅助分析,我这里直接引用了。
********************sample***********************
ServiceA {  
      
     /** 
      * 事务属性配置为 PROPAGATION_REQUIRED 
      */ 
     void methodA() {  
         ServiceB.methodB();  
     }  
 
}  
 
ServiceB {  
      
     /** 
      * 事务属性配置为 PROPAGATION_REQUIRED 
      */   
     void methodB() {  
     }  
      
}     
*************************************************
我们这里一个个分析吧
1: PROPAGATION_REQUIRED
加入当前正要执行的事务不在另外一个事务里,那么就起一个新的事务
比如说,ServiceB.methodB的事务级别定义为PROPAGATION_REQUIRED, 那么由于执行ServiceA.methodA的时候,
         ServiceA.methodA已经起了事务,这时调用ServiceB.methodB,ServiceB.methodB看到自己已经运行在ServiceA.methodA
的事务内部,就不再起新的事务。而假如ServiceA.methodA运行的时候发现自己没有在事务中,他就会为自己分配一个事务。
这样,在ServiceA.methodA或者在ServiceB.methodB内的任何地方出现异常,事务都会被回滚。即使ServiceB.methodB的事务已经被
提交,但是ServiceA.methodA在接下来fail要回滚,ServiceB.methodB也要回滚
2:   PROPAGATION_SUPPORTS
如果当前在事务中,即以事务的形式运行,如果当前不再一个事务中,那么就以非事务的形式运行
这就跟平常用的普通非事务的代码只有一点点区别了。不理这个,因为我也没有觉得有什么区别
3:   PROPAGATION_MANDATORY
必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常。
4:   PROPAGATION_REQUIRES_NEW
这个就比较绕口了。 比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED,ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW,
那么当执行到ServiceB.methodB的时候,ServiceA.methodA所在的事务就会挂起,ServiceB.methodB会起一个新的事务,等待ServiceB.methodB的事务完成以后,
他才继续执行。他与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为ServiceB.methodB是新起一个事务,那么就是存在
两个不同的事务。如果ServiceB.methodB已经提交,那么ServiceA.methodA失败回滚,ServiceB.methodB是不会回滚的。如果ServiceB.methodB失败回滚,
如果他抛出的异常被ServiceA.methodA捕获,ServiceA.methodA事务仍然可能提交。
5:   PROPAGATION_NOT_SUPPORTED
当前不支持事务。比如ServiceA.methodA的事务级别是PROPAGATION_REQUIRED ,而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ,
那么当执行到ServiceB.methodB时,ServiceA.methodA的事务挂起,而他以非事务的状态运行完,再继续ServiceA.methodA的事务。
6:   PROPAGATION_NEVER
不能在事务中运行。假设ServiceA.methodA的事务级别是PROPAGATION_REQUIRED, 而ServiceB.methodB的事务级别是PROPAGATION_NEVER ,
那么ServiceB.methodB就要抛出异常了。
7:   PROPAGATION_NESTED
理解Nested的关键是savepoint。他与PROPAGATION_REQUIRES_NEW的区别是,PROPAGATION_REQUIRES_NEW另起一个事务,将会与他的父事务相互独立,
而Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。
而Nested事务的好处是他有一个savepoint。
*****************************************
ServiceA {  
      
     /** 
      * 事务属性配置为 PROPAGATION_REQUIRED 
      */ 
     void methodA() {  
         try {
      //savepoint  
             ServiceB.methodB();    //PROPAGATION_NESTED 级别
         } catch (SomeException) {  
             // 执行其他业务, 如 ServiceC.methodC();  
         }  
     }  
 
}  
********************************************
也就是说ServiceB.methodB失败回滚,那么ServiceA.methodA也会回滚到savepoint点上,ServiceA.methodA可以选择另外一个分支,比如
ServiceC.methodC,继续执行,来尝试完成自己的事务。
但是这个事务并没有在EJB标准中定义。

二、Isolation Level(事务隔离等级):
1、Serializable:最严格的级别,事务串行执行,资源消耗最大;

2、REPEATABLE READ:保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。

3、READ COMMITTED:大多数主流数据库的默认事务等级,保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读取”。该级别适用于大多数系统。

4、Read Uncommitted:保证了读取过程中不会读取到非法数据。
隔离级别在于处理多事务的并发问题。
我们知道并行可以提高数据库的吞吐量和效率,但是并不是所有的并发事务都可以并发运行,这需要查看数据库教材的可串行化条件判断了。
这里就不阐述。
我们首先说并发中可能发生的3中不讨人喜欢的事情
1:   Dirty reads--读脏数据。也就是说,比如事务A的未提交(还依然缓存)的数据被事务B读走,如果事务A失败回滚,会导致事务B所读取的的数据是错误的。

2:   non-repeatable reads--数据不可重复读。比如事务A中两处读取数据-total-的值。在第一读的时候,total是100,然后事务B就把total的数据改成200,事务A再读一次,结果就发现,total竟然就变成200了,造成事务A数据混乱。

3:   phantom reads--幻象读数据,这个和non-repeatable reads相似,也是同一个事务中多次读不一致的问题。但是non-repeatable reads的不一致是因为他所要取的数据集被改变了(比如total的数据),但是phantom reads所要读的数据的不一致却不是他所要读的数据集改变,而是他的条件数据集改变。比如Select account.id where account.name="ppgogo*",第一次读去了6个符合条件的id,第二次读取的时候,由于事务b把一个帐号的名字由"dd"改成"ppgogo1",结果取出来了7个数据。
                          Dirty reads          non-repeatable reads            phantom reads
Serializable                     不会                   不会                           不会
REPEATABLE READ           不会                   不会                            会
READ COMMITTED            不会                    会                             会
Read Uncommitted            会                     会                             会

三、readOnly
事务属性中的readOnly标志表示对应的事务应该被最优化为只读事务。这是一个最优化提示。在一些情况下,一些事务策略能够起到显著的最优化效果,例如在使用Object/Relational映射工具(如:Hibernate或TopLink)时避免dirty checking(试图“刷新”)。
四、Timeout
       在事务属性中还有定义“timeout”值的选项,指定事务超时为几秒。在JTA中,这将被简单地传递到J2EE服务器的事务协调程序,并据此得到相应的解释。
分享到:
评论

相关推荐

    Spring事务传播特性解析

    通过代码解析spring传播特性,包括 1、Propagation.REQUIRED 方法被调用时自动开启事务,在事务范围内使用则使用同一个事务,否则开启新事务。 2、Propagation.REQUIRES_NEW 无论何时自身都会开启事务 3、...

    Spring在Transaction事务传播行为种类

    -- 下面定义事务传播属性 --> *">PROPAGATION_REQUIRED *">PROPAGATION_REQUIRED,readOnly *">PROPAGATION_REQUIRED *">PROPAGATION_REQUIRED *">PROPAGATION_REQUIRED <!-- 定义...

    02-01-10-Spring事务传播原理及数据库事务操作原理1

    在本课程中,我们将深入探讨Spring事务传播原理和数据库事务操作的基本概念,这对于有Spring开发经验的人员来说,是进一步深化事务控制理解的关键。我们还将触及分布式事务的初步知识,帮助开发者更好地掌握基于...

    通过实际案例摸清楚Spring事务传播的行为.docx

    通过这样的实际案例分析,我们可以更直观地看到不同事务传播行为在实际应用中的效果,从而加深对Spring事务管理的理解。在实际开发中,根据业务需求正确选择事务传播行为,有助于保证数据的一致性和完整性。

    spring学习事务源码

    此外,Spring的事务传播行为(PROPAGATION_REQUIRED, PROPAGATION_REQUIRES_NEW等)是另一个重要概念,它定义了在一个事务中的方法如何启动新的事务或者加入到当前事务中。例如,PROPAGATION_REQUIRED表示如果当前...

    spring 事务(6中配置完全降解)

    本篇文章将详细解析Spring中的六种事务配置方法,帮助开发者深入理解并掌握Spring事务的运用。 1. **基于XML的事务配置** Spring支持通过XML配置来管理事务,这是最基础的配置方式。在`spring`的配置文件中,我们...

    Spring事务类型祥解

    - `propagation`: 事务传播行为,如`REQUIRED`(默认)表示如果当前没有事务,则新建一个;`SUPPORTS`表示如果已有事务就加入,没有则不开启新事务等。 - `isolation`: 事务隔离级别,如`DEFAULT`(默认)遵循数据库...

    Spring自定义切面事务问题

    这可能会影响到事务的传播行为。 3. **解决方案:正确配置事务切面的顺序** - 在Spring中,事务管理器本身也可以被看作是一种切面,它负责在合适的时候开启和提交事务。因此,当有多个切面需要被应用到同一个方法...

    Spring事务属性

    本文将详细解析Spring事务属性中的四个关键元素:事务隔离级别、事务传播行为、事务超时时间以及事务是否只读。 首先,我们来探讨事务隔离级别。事务隔离级别是解决并发事务可能导致的问题,如脏读、不可重复读和幻...

    spring事务管理

    1. **事务定义**:`DefaultTransactionDefinition`用于设置事务的一些属性,如隔离级别、传播行为等。 2. **事务状态**:`TransactionStatus`对象表示当前事务的状态。 3. **事务管理器**:`...

    spring事务代码解读(转)

    如果事务传播属性为PROPAGATION_REQUIRED,那么AService和BService在同一事务中执行,即使BService出现异常,整个事务也会在AService方法返回后被回滚。 5. 事务的回滚逻辑在`doCloseTransactionAfterThrowing`方法...

    第八节-spring-事物源码解析1

    本节将深入探讨Spring事务的源码解析,特别是涉及的事务概念、三大核心接口以及相关属性。 1. **事务概念解析** 事务是数据库操作的基本单位,它封装了一组数据库操作,遵循ACID(原子性、一致性、隔离性和持久性...

    Spring源码解析.zip

    本压缩包“Spring源码解析”提供了对Spring框架核心组件——IOC(Inversion of Control,控制反转)、AOP(Aspect Oriented Programming,面向切面编程)以及Transaction(事务管理)的源码分析,帮助开发者更全面地...

    这一次搞懂Spring事务注解的解析方式

    【Spring 事务注解解析方式】 在Spring框架中,事务管理是通过AOP(面向切面编程)实现的,提供了...通过理解这些核心概念和机制,我们可以更深入地掌握Spring事务注解的工作原理,避免在实际开发中遇到不必要的问题。

    Spring源代码解析

    4. 事务传播行为:不同的方法调用场景下,事务的传播行为可能不同,如REQUIRED(默认,必须在事务中运行)、SUPPORTS(如果存在事务则加入,否则不开启新的事务)等。 5. 事务回滚规则:异常类型和是否包含在@...

    spring事务全解释

    本篇文章将深入解析Spring事务的方方面面,帮助你全面理解这个强大的特性。 首先,我们要明白什么是事务。事务是数据库操作的基本单位,它保证了一组数据库操作要么全部成功,要么全部失败,从而维护数据的一致性。...

    第十四章 Spring4 切面事物与事物通知与传播行为

    Spring定义了七种事务传播行为: 1. REQUIRED:默认设置,如果当前存在事务,则加入该事务;如果没有,则创建一个新的事务。 2. SUPPORTS:如果当前存在事务,则加入该事务;如果没有,也不会创建新的事务。 3. ...

    spring源代码解析

    5. **事务管理**:"spring源代码解析(六):spring声明式事物处理.doc"分析了Spring如何提供声明式事务管理,包括@Transactional注解的工作原理和事务传播行为。 6. **Spring与Hibernate集成**:"spring源代码解析...

    Spring事务详解

    1. 事务的传播行为:由`getPropagationBehavior()`返回,Spring定义了7种事务传播行为: - `PROPAGATION_REQUIRED`:默认行为,如果当前存在事务,则加入到该事务;如果不存在,则新建一个事务。 - `PROPAGATION_...

    Spring4--3.jdbcTemplate事务

    - **事务传播行为**:定义了如何在嵌套事务中处理事务边界,如REQUIRED(默认,如果已有事务则加入,没有则新建)、REQUIRES_NEW(始终新建一个事务)等。 在实际应用中,通常会结合使用JdbcTemplate和声明式事务...

Global site tag (gtag.js) - Google Analytics