`
fantaxy025025
  • 浏览: 1309290 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

spring嵌套事务spring的事物种类

 
阅读更多

 

http://www.iteye.com/topic/35907

主题:解惑 spring 嵌套事务

解惑 spring 嵌套事务 

/** 
  * @author 王政 
  * @date 2006-11-24 
  * @note 转载请注明出处 
  */ 

   在所有使用 spring 的应用中, 声明式事务管理可能是使用率最高的功能了, 但是, 从我观察到的情况看, 
绝大多数人并不能深刻理解事务声明中不同事务传播属性配置的的含义, 让我们来看一下 TransactionDefinition 接口中的定义 

Java代码  收藏代码
  1. /** 
  2.      * Support a current transaction, create a new one if none exists. 
  3.      * Analogous to EJB transaction attribute of the same name. 
  4.      * <p>This is typically the default setting of a transaction definition. 
  5.      */  
  6.     int PROPAGATION_REQUIRED = 0;  
  7.   
  8.     /** 
  9.      * Support a current transaction, execute non-transactionally if none exists. 
  10.      * Analogous to EJB transaction attribute of the same name. 
  11.      * <p>Note: For transaction managers with transaction synchronization, 
  12.      * PROPAGATION_SUPPORTS is slightly different from no transaction at all, 
  13.      * as it defines a transaction scopp that synchronization will apply for. 
  14.      * As a consequence, the same resources (JDBC Connection, Hibernate Session, etc) 
  15.      * will be shared for the entire specified scope. Note that this depends on 
  16.      * the actual synchronization configuration of the transaction manager. 
  17.      * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization 
  18.      */  
  19.     int PROPAGATION_SUPPORTS = 1;  
  20.   
  21.     /** 
  22.      * Support a current transaction, throw an exception if none exists. 
  23.      * Analogous to EJB transaction attribute of the same name. 
  24.      */  
  25.     int PROPAGATION_MANDATORY = 2;  
  26.   
  27.     /** 
  28.      * Create a new transaction, suspend the current transaction if one exists. 
  29.      * Analogous to EJB transaction attribute of the same name. 
  30.      * <p>Note: Actual transaction suspension will not work on out-of-the-box 
  31.      * on all transaction managers. This in particular applies to JtaTransactionManager, 
  32.      * which requires the <code>javax.transaction.TransactionManager</code> to be 
  33.      * made available it to it (which is server-specific in standard J2EE). 
  34.      * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager 
  35.      */  
  36.     int PROPAGATION_REQUIRES_NEW = 3;  
  37.   
  38.     /** 
  39.      * Execute non-transactionally, suspend the current transaction if one exists. 
  40.      * Analogous to EJB transaction attribute of the same name. 
  41.      * <p>Note: Actual transaction suspension will not work on out-of-the-box 
  42.      * on all transaction managers. This in particular applies to JtaTransactionManager, 
  43.      * which requires the <code>javax.transaction.TransactionManager</code> to be 
  44.      * made available it to it (which is server-specific in standard J2EE). 
  45.      * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager 
  46.      */  
  47.     int PROPAGATION_NOT_SUPPORTED = 4;  
  48.   
  49.     /** 
  50.      * Execute non-transactionally, throw an exception if a transaction exists. 
  51.      * Analogous to EJB transaction attribute of the same name. 
  52.      */  
  53.     int PROPAGATION_NEVER = 5;  
  54.   
  55.     /** 
  56.      * Execute within a nested transaction if a current transaction exists, 
  57.      * behave like PROPAGATION_REQUIRED else. There is no analogous feature in EJB. 
  58.      * <p>Note: Actual creation of a nested transaction will only work on specific 
  59.      * transaction managers. Out of the box, this only applies to the JDBC 
  60.      * DataSourceTransactionManager when working on a JDBC 3.0 driver. 
  61.      * Some JTA providers might support nested transactions as well. 
  62.      * @see org.springframework.jdbc.datasource.DataSourceTransactionManager 
  63.      */  
  64.     int PROPAGATION_NESTED = 6;  



我们可以看到, 在 spring 中一共定义了六种事务传播属性, 如果你觉得看起来不够直观, 那么我来转贴一个满大街都有的翻译 

引用

PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 
PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。 
PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。 
PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。 
PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 
PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。 
PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。 
前六个策略类似于EJB CMT,第七个(PROPAGATION_NESTED)是Spring所提供的一个特殊变量。 
它要求事务管理器或者使用JDBC 3.0 Savepoint API提供嵌套事务行为(如Spring的DataSourceTransactionManager) 



在我所见过的误解中, 最常见的是下面这种: 

引用

假如有两个业务接口 ServiceA 和 ServiceB, 其中 ServiceA 中有一个方法实现如下 

/** 
* 事务属性配置为 PROPAGATION_REQUIRED 
*/ 
void methodA() { 
// 调用 ServiceB 的方法 
ServiceB.methodB(); 


那么如果 ServiceB 的 methodB  如果配置了事务, 就必须配置为 PROPAGATION_NESTED 



这种想法可能害了不少人, 认为 Service 之间应该避免互相调用, 其实根本不用担心这点,PROPAGATION_REQUIRED 已经说得很明白, 
如果当前线程中已经存在事务, 方法调用会加入此事务, 果当前没有事务,就新建一个事务, 所以 ServiceB#methodB() 的事务只要遵循最普通的规则配置为 PROPAGATION_REQUIRED 即可, 如果 ServiceB#methodB (我们称之为内部事务, 为下文打下基础) 抛了异常, 那么 ServiceA#methodA(我们称之为外部事务) 如果没有特殊配置此异常时事务提交 (即 +MyCheckedException的用法), 那么整个事务是一定要 rollback 的, 什么 Service 只能调 Dao 之类的言论纯属无稽之谈, spring 只负责配置了事务属性方法的拦截, 它怎么知道你这个方法是在 Service 还是 Dao 里 ? 

     说了这么半天, 那到底什么是真正的事务嵌套呢, 解释之前我们来看一下  Juergen Hoeller 的原话 

Juergen Hoeller 写道

PROPAGATION_REQUIRES_NEW starts a new, independent "inner" transaction for the given scope. This transaction will be committed or rolled back completely independent from the outer transaction, having its own isolation scope, its own set of locks, etc. The outer transaction will get suspended at the beginning of the inner one, and resumed once the inner one has completed. 

Such independent inner transactions are for example used for id generation through manual sequences, where the access to the sequence table should happen in its own transactions, to keep the lock there as short as possible. The goal there is to avoid tying the sequence locks to the (potentially much longer running) outer transaction, with the sequence lock not getting released before completion of the outer transaction. 

PROPAGATION_NESTED on the other hand starts a "nested" transaction, which is a true subtransaction of the existing one. What will happen is that a savepoint will be taken at the start of the nested transaction. íf the nested transaction fails, we will roll back to that savepoint. The nested transaction is part of of the outer transaction, so it will only be committed at the end of of the outer transaction. 

Nested transactions essentially allow to try some execution subpaths as subtransactions: rolling back to the state at the beginning of the failed subpath, continuing with another subpath or with the main execution path there - all within one isolated transaction, and not losing any previous work done within the outer transaction. 

For example, consider parsing a very large input file consisting of account transfer blocks: The entire file should essentially be parsed within one transaction, with one single commit at the end. But if a block fails, its transfers need to be rolled back, writing a failure marker somewhere. You could either start over the entire transaction every time a block fails, remembering which blocks to skip - or you mark each block as a nested transaction, only rolling back that specific set of operations, keeping the previous work of the outer transaction. The latter is of course much more efficient, in particular when a block at the end of the file fails. 



Juergen Hoeller 写道

Rolling back the entire transaction is the choice of the demarcation code/config that started the outer transaction. 

So if an inner transaction throws an exception and is supposed to be rolled back (according to the rollback rules), the transaction will get rolled back to the savepoint taken at the start of the inner transaction. The immediate calling code can then decide to catch the exception and proceed down some other path within the outer transaction. 

If the code that called the inner transaction lets the exception propagate up the call chain, the exception will eventually reach the demarcation code of the outer transaction. At that point, the rollback rules of the outer transaction decide whether to trigger a rollback. That would be a rollback of the entire outer transaction then. 

So essentially, it depends on your exception handling. If you catch the exception thrown by the inner transaction, you can proceed down some other path within the outer transaction. If you let the exception propagate up the call chain, it's eventually gonna cause a rollback of the entire outer transaction. 



    也就是说, 最容易弄混淆的其实是 PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED, 那么这两种方式又有何区别呢? 我简单的翻译一下 Juergen Hoeller 的话 : 
    
    PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 "内部" 事务. 这个事务将被完全 commited 或 rolled back 而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等. 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行. 


    另一方面, PROPAGATION_NESTED 开始一个 "嵌套的" 事务,  它是已经存在事务的一个真正的子事务. 潜套事务开始执行时,  它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交. 

    由此可见, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于, PROPAGATION_REQUIRES_NEW 完全是一个新的事务, 而 PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 潜套事务也会被 commit, 这个规则同样适用于 roll back. 
    
    
    那么外部事务如何利用嵌套事务的 savepoint 特性呢, 我们用代码来说话 
    

Java代码  收藏代码
  1. ServiceA {  
  2.       
  3.     /** 
  4.      * 事务属性配置为 PROPAGATION_REQUIRED 
  5.      */  
  6.     void methodA() {  
  7.         ServiceB.methodB();  
  8.     }  
  9.   
  10. }  
  11.   
  12. ServiceB {  
  13.       
  14.     /** 
  15.      * 事务属性配置为 PROPAGATION_REQUIRES_NEW 
  16.      */   
  17.     void methodB() {  
  18.     }  
  19.       
  20. }     

    

这种情况下, 因为 ServiceB#methodB 的事务属性为 PROPAGATION_REQUIRES_NEW, 所以两者不会发生任何关系, ServiceA#methodA 和 ServiceB#methodB 不会因为对方的执行情况而影响事务的结果, 因为它们根本就是两个事务, 在 ServiceB#methodB 执行时 ServiceA#methodA 的事务已经挂起了 (关于事务挂起的内容已经超出了本文的讨论范围, 有时间我会再写一些挂起的文章) . 

那么 PROPAGATION_NESTED 又是怎么回事呢? 继续看代码 

Java代码  收藏代码
  1. ServiceA {  
  2.       
  3.     /** 
  4.      * 事务属性配置为 PROPAGATION_REQUIRED 
  5.      */  
  6.     void methodA() {  
  7.         ServiceB.methodB();  
  8.     }  
  9.   
  10. }  
  11.   
  12. ServiceB {  
  13.       
  14.     /** 
  15.      * 事务属性配置为 PROPAGATION_NESTED 
  16.      */   
  17.     void methodB() {  
  18.     }  
  19.       
  20. }     



现在的情况就变得比较复杂了, ServiceB#methodB 的事务属性被配置为 PROPAGATION_NESTED, 此时两者之间又将如何协作呢? 从 Juergen Hoeller 的原话中我们可以找到答案, ServiceB#methodB 如果 rollback, 那么内部事务(即 ServiceB#methodB) 将回滚到它执行前的 SavePoint(注意, 这是本文中第一次提到它, 潜套事务中最核心的概念), 而外部事务(即 ServiceA#methodA) 可以有以下两种处理方式: 

1. 改写 ServiceA 如下 

Java代码  收藏代码
  1. ServiceA {  
  2.       
  3.     /** 
  4.      * 事务属性配置为 PROPAGATION_REQUIRED 
  5.      */  
  6.     void methodA() {  
  7.         try {  
  8.             ServiceB.methodB();  
  9.         } catch (SomeException) {  
  10.             // 执行其他业务, 如 ServiceC.methodC();  
  11.         }  
  12.     }  
  13.   
  14. }  



这种方式也是潜套事务最有价值的地方, 它起到了分支执行的效果, 如果 ServiceB.methodB 失败, 那么执行 ServiceC.methodC(), 而 ServiceB.methodB 已经回滚到它执行之前的 SavePoint, 所以不会产生脏数据(相当于此方法从未执行过), 这种特性可以用在某些特殊的业务中, 而 PROPAGATION_REQUIRED 和 PROPAGATION_REQUIRES_NEW 都没有办法做到这一点. (题外话 : 看到这种代码, 似乎似曾相识, 想起了 prototype.js 中的 Try 函数 ) 

2. 代码不做任何修改, 那么如果内部事务(即 ServiceB#methodB) rollback, 那么首先 ServiceB.methodB 回滚到它执行之前的 SavePoint(在任何情况下都会如此), 
   外部事务(即 ServiceA#methodA) 将根据具体的配置决定自己是 commit 还是 rollback (+MyCheckedException). 
   
   
上面大致讲述了潜套事务的使用场景, 下面我们来看如何在 spring 中使用 PROPAGATION_NESTED, 首先来看 AbstractPlatformTransactionManager 

Java代码  收藏代码
  1. /** 
  2.  * Create a TransactionStatus for an existing transaction. 
  3.  */  
  4. private TransactionStatus handleExistingTransaction(  
  5.         TransactionDefinition definition, Object transaction, boolean debugEnabled)  
  6.         throws TransactionException {  
  7.   
  8.    ... 省略  
  9.   
  10.     if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {  
  11.         if (!isNestedTransactionAllowed()) {  
  12.             throw new NestedTransactionNotSupportedException(  
  13.                     "Transaction manager does not allow nested transactions by default - " +  
  14.                     "specify 'nestedTransactionAllowed' property with value 'true'");  
  15.         }  
  16.         if (debugEnabled) {  
  17.             logger.debug("Creating nested transaction with name [" + definition.getName() + "]");  
  18.         }  
  19.         if (useSavepointForNestedTransaction()) {  
  20.             // Create savepoint within existing Spring-managed transaction,  
  21.             // through the SavepointManager API implemented by TransactionStatus.  
  22.             // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.  
  23.             DefaultTransactionStatus status =  
  24.                     newTransactionStatus(definition, transaction, falsefalse, debugEnabled, null);  
  25.             status.createAndHoldSavepoint();  
  26.             return status;  
  27.         }  
  28.         else {  
  29.             // Nested transaction through nested begin and commit/rollback calls.  
  30.             // Usually only for JTA: Spring synchronization might get activated here  
  31.             // in case of a pre-existing JTA transaction.  
  32.             doBegin(transaction, definition);  
  33.             boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);  
  34.             return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);  
  35.         }  
  36.     }  
  37. }  


   
一目了然 

1. 我们要设置 transactionManager 的 nestedTransactionAllowed 属性为 true, 注意, 此属性默认为 false!!! 

再看 AbstractTransactionStatus#createAndHoldSavepoint() 方法 

Java代码  收藏代码
  1. /** 
  2.  * Create a savepoint and hold it for the transaction. 
  3.  * @throws org.springframework.transaction.NestedTransactionNotSupportedException 
  4.  * if the underlying transaction does not support savepoints 
  5.  */  
  6. public void createAndHoldSavepoint() throws TransactionException {  
  7.     setSavepoint(getSavepointManager().createSavepoint());  
  8. }  



  可以看到 Savepoint 是 SavepointManager.createSavepoint 实现的, 再看 SavepointManager 的层次结构, 发现 
  其 Template 实现是 JdbcTransactionObjectSupport, 常用的 DatasourceTransactionManager, HibernateTransactionManager 
  中的 TransactonObject 都是它的子类 : 

 
   
  JdbcTransactionObjectSupport 告诉我们必须要满足两个条件才能 createSavepoint : 
  
2. java.sql.Savepoint 必须存在, 即 jdk 版本要 1.4+ 
3. Connection.getMetaData().supportsSavepoints() 必须为 true, 即 jdbc drive 必须支持 JDBC 3.0 


确保以上条件都满足后, 你就可以尝试使用 PROPAGATION_NESTED 了. (全文完) 

 

我这里再转一篇嵌套事务的文章供大家参考, 文章来自于 
http://book.csdn.net/bookfiles/121/1001213920.shtml 



显式事务可以嵌套,即在显式事务中开始另一个显式事务是可能的。支持嵌套事务的最重要原因是为了允许在存储过程中使用事务而不必顾及这个事务本身是否是在另一个事务中被调用的。但是SQL Server是如何处理嵌套事务的?我们可以通过两个简单的示例来探究一下嵌套事务。 

Ø       探究嵌套事务 

1.    启动SQL Server Management Studio并打开一个“新建查询”窗口。 

2.    通过@@TRANCOUNT来发现SQL Server是如何处理嵌套事务的。键入并执行以下批(此例的代码包含在示例文件NestingTransactions.sql中): 


Java代码  收藏代码
  1. PRINT 'Trancount before transaction: ' + CAST(@@trancount as char(1))  
  2.   
  3. BEGIN TRAN  
  4.   
  5.     PRINT 'After first BEGIN TRAN: ' + CAST(@@trancount as char(1))  
  6.   
  7.     BEGIN TRAN  
  8.   
  9.         PRINT 'After second BEGIN TRAN: ' + CAST(@@trancount as char(1))  
  10.   
  11.     COMMIT TRAN  
  12.   
  13.     PRINT 'After first COMMIT TRAN: ' + CAST(@@trancount as char(1))  
  14.   
  15. COMMIT TRAN  
  16.   
  17. PRINT 'After second COMMIT TRAN: ' + CAST(@@trancount as char(1))  




3.    在结果中,可以看到每一个BEGIN TRAN 语句都会使@@TRANCOUNT增加1并且每一个COMMIT TRAN语句都会使其减少1。如前所述,一个值为0的@@TRANCOUNT意味着没有打开的事务。因此,在@@TRANCOUNT值从1降到0时结束的事务发生在外层事务提交的时候。因此,每一个内部事务都需要提交。由于事务起始于第一个BEGIN TRAN并结束于最后一个COMMIT TRAN,因此最外层的事务决定了是否完全提交内部的事务。如果最外层的事务没有被提交,其中嵌套的事务也不会被提交。 

4.    键入并执行以下批来检验事务回滚时所发生的情况: 


Java代码  收藏代码
  1. USE AdventureWorks  
  2.   
  3. BEGIN TRAN  
  4.   
  5.     PRINT 'After 1st BEGIN TRAN: ' + CAST(@@trancount as char(1))  
  6.   
  7.     BEGIN TRAN  
  8.   
  9.         PRINT 'After 2nd BEGIN TRAN: ' + CAST(@@trancount as char(1))  
  10.   
  11.             BEGIN TRAN  
  12.   
  13.             PRINT 'After 3rd BEGIN TRAN: ' + CAST(@@trancount as char(1))  
  14.   
  15.    
  16.   
  17.             UPDATE Person.Contact  
  18.   
  19.             SET EmailAddress = 'test@test.at'  
  20.   
  21.             WHERE ContactID = 20  
  22.   
  23.    
  24.   
  25.             COMMIT TRAN  
  26.   
  27.         PRINT 'After first COMMIT TRAN: ' + CAST(@@trancount as char(1))  
  28.   
  29. ROLLBACK TRAN  
  30.   
  31. PRINT 'After ROLLBACK TRAN: ' + CAST(@@trancount as char(1))  
  32.   
  33.    
  34.   
  35. SELECT EmailAddress FROM Person.Contact  
  36.   
  37. WHERE ContactID = 20;  




5.    在这个示例中,联系人的电子邮件地址在一个嵌套事务中被更新,这会被立即提交。然后ROLLBACK TRAN被执行。ROLLBACK TRAN将@@TRANCOUNT减为0并回滚整个事务及其中嵌套的事务,无论它们是否已经被提交。因此,嵌套事务中所做的更新被回滚,数据没有任何改变。 

始终牢记,在嵌套的事务中,只有最外层的事务决定着是否提交内部事务。每一个COMMIT TRAN语句总是应用于最后一个执行的BEGIN TRAN。因此,对于每一个BEGIN TRAN,必须调用一个COMMIT TRAN来提交事务。ROLLBACK TRAN语句总是属于最外层的事务,并且因此总是回滚整个事务而不论其中打开了多少嵌套事务。正因为此,管理嵌套事务很复杂。正如本节最初提到的那样,如果每一个嵌套存储过程都在自身中开始一个事务,那么嵌套事务大部分会发生在嵌套存储过程中。要避免嵌套事务,可以在过程开始处检查@@TRANCOUNT的值,以此来确定是否需要开始一个事务。如果@@TRANCOUNT大于0,因为过程已经处于一个事务中并且调用实例可以在错误发生时回滚事务。

 

-----------------------

看回复和讨论吧。

-----------------------

+

+

=

+

=

=

 

分享到:
评论

相关推荐

    Spring事务管理Demo

    - `NESTED`:如果当前存在事务,则在嵌套事务内运行;如果没有事务,则行为类似于`REQUIRED`。 Spring事务管理的隔离级别包括: - `DEFAULT`:使用数据库的默认隔离级别。 - `READ_UNCOMMITTED`:最低隔离级别,...

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

    7. NESTED:如果当前存在事务,则创建一个嵌套事务;如果没有,则行为同REQUIRED。 理解并熟练运用这些概念,可以帮助开发者更高效地利用Spring框架实现复杂的应用逻辑,同时保持代码的整洁和可维护性。通过阅读...

    spring事物传播测试表

    7. NESTED:如果当前存在事务,则创建一个嵌套事务,它会在当前事务内部执行。如果当前没有事务,则行为类似于REQUIRED。 “事务传播测试表”通常用于记录和分析这些行为在不同场景下的表现,以便于开发者理解和...

    Spring 管理事务(传播特性、隔离级别、readonly).rar

    - NESTED:如果当前存在事务,则在嵌套事务内执行;如果不存在,则按REQUIRED行为执行。 2. 事务的隔离级别: 隔离级别用于解决并发控制中可能出现的问题,如脏读、不可重复读和幻读。Spring支持四种隔离级别: ...

    spring事物的7大传播机制,5个隔离机制

    这提供了一种嵌套事务的能力,允许在一个事务中开启另一个事务。 ### Spring事务的五个隔离级别 事务的隔离级别决定了多个并发事务之间数据的一致性程度。Spring支持以下五种隔离级别: #### 1. ISOLATION_...

    Spring中的声明式事物

    - `NESTED`:如果存在事务,则在嵌套事务内运行;若无事务,则行为类似于`REQUIRED`。 4. **事务的隔离级别** - `DEFAULT`:使用数据库默认的隔离级别。 - `READ_UNCOMMITTED`:最低级别,允许读取未提交的数据...

    Spring中事务传播行为的介绍

    2. PROPAGATION_NESTED:嵌套事务,表示如果当前有一个事务正在运行当中,则该方法应该运行在一个嵌套事务中。被嵌套的事务可以独立于封装事务进行提交或回滚。如果封装事务不存在,则行为就像 PROPAGATION_REQUIRED...

    spring 事物底层原理分析1

    - NESTED:如果当前存在事务,则创建一个嵌套事务;如果没有事务,则按照REQUIRED行为处理。 理解这些传播行为有助于在多层方法调用中正确地管理事务边界,确保事务的正确性和一致性。 综上所述,Spring 事务管理...

    Spring事务传播机制.docx

    7. **PROPAGATION_NESTED**:如果当前存在事务,则在嵌套事务内执行;如果不存在,则行为类似于PROPAGATION_REQUIRED。 事务隔离级别的选择和事务传播行为的设定,对于确保数据一致性至关重要。例如,如果你的应用...

    AOP实现自我调用的事物嵌套问题

    当我们遇到"AOP实现自我调用的事物嵌套问题"时,这通常涉及到Spring框架中的事务管理,特别是自调用方法在事务处理时可能会引发的问题。 首先,让我们理解Spring AOP的事务管理是如何工作的。Spring使用代理模式来...

    spring事物管理

    7. **PROPAGATION_NESTED**:如果当前存在事务,那么在嵌套事务内执行,如果当前没有事务,行为类似于PROPAGATION_REQUIRED。这种传播行为需要数据库支持保存点,使得可以在事务内部创建子事务,回滚子事务不会影响...

    Spring Boot数据库事务控制.zip

    6. **事务嵌套**:在同一个事务中调用另一个@Transactional方法,Spring会处理这种事务嵌套。默认情况下,子事务将继承父事务的隔离级别和传播行为。 7. **事物边界**:理解事务边界是确保事务正确性的关键。事务...

    spring事物隔离和传播机制

    - 描述:如果当前存在事务,则在嵌套事务内执行;如果当前不存在事务,则执行与 `PROPAGATION_REQUIRED` 类似的操作。 - 应用场景:适用于需要在现有事务中开启新事务的场景,比如日志记录等。 #### 二、Spring ...

    spring 事物总结

    - NESTED:如果当前存在事务,则在嵌套事务内执行;如果不存在,则按REQUIRED方式执行。 6. **事务的隔离级别** - READ_UNCOMMITTED:最低隔离级别,允许脏读、不可重复读和幻读。 - READ_COMMITTED:防止脏读,...

    spring事物传播propagation类别含义详解

    7. nested:如果当前有事务,则开启子事务(嵌套事务),嵌套事务式独立提交或者回滚;如果当前没有事务,则跟required一样。如果主事务提交,则会携带子事务一起提交;如果主事务回滚,则子事务会一起回滚。相反子...

    SpringHibernate事务及传播特性

    7. **PROPAGATION_NESTED**:如果当前存在事务,则在嵌套事务内运行;如果没有事务,则行为类似于PROPAGATION_REQUIRED。 在Hibernate中,事务管理通常通过Session接口进行,包括beginTransaction()、commit()和...

    深入理解Spring事务的传播行为

    嵌套事务的特点是,子事务的回滚只会影响其自身,不会影响外层事务,除非外层事务也选择回滚。 通过实例代码,我们可以更清晰地理解这些传播行为。例如,有两个服务`ServiceA`和`ServiceB`,`ServiceA`调用`...

    事务传播特性&事务隔离级别

    7. PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按 TransactionDefinition.PROPAGATION_REQUIRED 属性执行。 事务隔离级别是指数据库事务的隔离级别,用于控制...

Global site tag (gtag.js) - Google Analytics