引言
本篇博文小猿主要是针对事务的应用,而事务的传播行为有7类,这7种传播行为各有不同的应用场景,以下小猿将论述7种传播行为各自的特点
函数关系
REQUIED
/**
* Support a current transaction, create a new one if none exists.
* Analogous to EJB transaction attribute of the same name.
* <p>This is the default setting of a transaction annotation.
*/
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
case1
上述图中最后一句写的不好,应该是两个children方法执行保存失败,而不是不执行。
case2
上述图中虽然在函数2中添加了事务,但应为函数1中已经有事务,而传播行为required,这说明当执行函数2时,看到函数1已经存在时候,则直接加入函数1的事务,自己就不再创建新事务,这种现象就是required事务的传播,此时无论函数是否有事务注解都无关紧要,子事务都会加入到父事务中, 按照事务的原子性,此时采用函数1的事务,则中间如果出现一次异常,这此次事务全部执行失败。
完全回滚。
require传播行为可以总结为老板有饭吃,我就蹭饭吃,老板没饭吃,我就自己买。
support
support的源码显示如下
/**
* Support a current transaction, execute non-transactionally if none exists.
* Analogous to EJB transaction attribute of the same name.
* <p>Note: For transaction managers with transaction synchronization,
* {@code SUPPORTS} is slightly different from no transaction at all,
* as it defines a transaction scope 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
*/
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
case1
数据库中没有任何记录
case2
supports传播行为可以总结老板有饭我就蹭饭,老板没饭我就绝食。一般来说supports用于查询业务。
MANDATORY
下面先来看源码
/**
* Support a current transaction, throw an exception if none exists.
* Analogous to EJB transaction attribute of the same name.
*/
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
当前没有事务则直接抛出异常。
case1
case2
MANDATORY可以总结为: 老板不给饭吃我就罢工
REQUIRES_NEW
/**
* Create a new transaction, and suspend the current transaction if one exists.
* Analogous to the EJB transaction attribute of the same name.
* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
* on all transaction managers. This in particular applies to
* {@link org.springframework.transaction.jta.JtaTransactionManager},
* which requires the {@code javax.transaction.TransactionManager} to be
* made available to it (which is server-specific in standard Java EE).
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
case1
case2
case3
REQUIRES_NEW可以总结为: 老板给的饭太难吃,我要自己订饭,老板不给饭吃,我要自己订饭
NOT_SUPPORTED
/**
* Execute non-transactionally, suspend the current transaction if one exists.
* Analogous to EJB transaction attribute of the same name.
* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
* on all transaction managers. This in particular applies to
* {@link org.springframework.transaction.jta.JtaTransactionManager},
* which requires the {@code javax.transaction.TransactionManager} to be
* made available to it (which is server-specific in standard Java EE).
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
碰到事务就挂起当前事务。
case1
case2
测试结果
NOT_SUPPORTED可以总结为: 老板给的饭吃,我太忙了,没空吃饭 。
NEVER
/**
* Execute non-transactionally, throw an exception if a transaction exists.
* Analogous to EJB transaction attribute of the same name.
*/
NEVER(TransactionDefinition.PROPAGATION_NEVER),
case1
case2
NEVER则可总结为老板太难吃,逼着我罢工。
NESTED
/**
* Execute within a nested transaction if a current transaction exists,
* behave like {@code REQUIRED} otherwise. There is no analogous feature in EJB.
* <p>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. Some JTA providers might support nested
* transactions as well.
* @see org.springframework.jdbc.datasource.DataSourceTransactionManager
*/
NESTED(TransactionDefinition.PROPAGATION_NESTED);
case1
父事务异常影响子事务提交。
子事务异常也会影响父事务的提交。
case2
加入保存点之后,子事务就不会影响父事务的提交。
测试结果:
NESTED则可总结为老板决策不对,东家就怪罪,全部没饭吃,我就跟着受罪;我干活不对,老板马上脱罪有饭吃,害的自己受累没饭吃
总结
- REQUIRED: 使用当前的事务,如果当前没有事务,则自己新建一个事务,子方法是必须运行在一个事务中的;
如果当前存在事务,则加入这个事务,成为一个整体。 - SUPPORTS: 如果当前有事务,则使用事务;如果当前没有事务,则不使用事务。
- MANDATORY: 该传播属性强制必须存在一个事务,如果不存在,则抛出异常
- REQUIRES_NEW: 如果当前有事务,则挂起该事务,并且自己创建一个新的事务给自己使用;
如果当前没有事务,则同 REQUIRED - NOT_SUPPORTED: 如果当前有事务,则把事务挂起,自己不适用事务去运行数据库操作
- NEVER: 如果当前有事务存在,则抛出异常
- NESTED: 如果当前有事务,则开启子事务(嵌套事务),嵌套事务是独立提交或者回滚;
如果当前没有事务,则同 REQUIRED。
但是如果主事务提交,则会携带子事务一起提交。
如果主事务回滚,则子事务会一起回滚。相反,子事务异常,则父事务可以回滚或不回滚。