Spring 中事务的传播性
在 Spring 中一共定义了七种事务传播属性:
- PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
- PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。
- PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。
- PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。
- PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
前六个策略类似于EJBCMT,第七个(PROPAGATION_NESTED)是Spring所提供的一个特殊变量。它要求事务管理器或者使用JDBC3.0SavepointAPI提供嵌套事务行为(如Spring的DataSourceTransactionManager)。
也就是说,最容易弄混淆的其实是PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED,那么这两种方式又有何区别呢?
PROPAGATION_REQUIRES_NEW启动一个新的,不依赖于环境的"内部"事务.这个事务将被完全commited或rolledback而不依赖于外部事务,它拥有自己的隔离范围,自己的锁,等等.当内部事务开始执行时,外部事务将被挂起,内务事务结束时,外部事务将继续执行.
另一方面,PROPAGATION_NESTED开始一个"嵌套的"事务,它是已经存在事务的一个真正的子事务.潜套事务开始执行时,它将取得一个savepoint.如果这个嵌套事务失败,我们将回滚到此savepoint.潜套事务是外部事务的一部分,只有外部事务结束后它才会被提交.
由此可见,PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED的最大区别在于,PROPAGATION_REQUIRES_NEW完全是一个新的事务,而PROPAGATION_NESTED则是外部事务的子事务,如果外部事务commit,潜套事务也会被commit,这个规则同样适用于rollback.
参考:
1、http://www.iteye.com/topic/35907
2、http://www.iteye.com/topic/78674
3、http://www.iteye.com/topic/199813