资源预览内容
第1页 / 共16页
第2页 / 共16页
第3页 / 共16页
第4页 / 共16页
第5页 / 共16页
第6页 / 共16页
第7页 / 共16页
第8页 / 共16页
第9页 / 共16页
第10页 / 共16页
亲,该文档总共16页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
解惑解惑 springspring 嵌套事务嵌套事务解惑 spring 嵌套事务 /* * author 王政 * date 2006-11-24 * note 转载请注明出处 */ 在所有使用 spring 的应用中, 声明式事务管理可能是使用率最高的功能了, 但是, 从我观察到的情况看, 绝大多数人并不能深刻理解事务声明中不同事务传播属性配置的的含义, 让我们来看一下 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; 我们可以看到, 在 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 transacti
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号