spring事务的传播机制定义在 TransactionDefinition 接口中,定义了如下传播类型
PROPAGATION_REQUIRED
支持当前事务,如果没有当前事务就创建一个新的事务,是默认的传播行为。
外围方法未开启事务
内部会创建新事务,若新事务回滚,不影响外围方法。
外围方法开启事务
内部方法会加入到外围方法的事务中,使用同一个事务,不管内外谁发生异常,整个事务都将回滚。
/**
* Support a current transaction; create a new one if none exists.
* Analogous to the EJB transaction attribute of the same name.
* <p>This is typically the default setting of a transaction definition,
* and typically defines a transaction synchronization scope.
*/
int PROPAGATION_REQUIRED = 0;
PROPAGATION_SUPPORTS
支持当前事务,如果没有事务就以非事务方式执行。
外围方法未开启事务
以非事务方法运行。
外围方法开启事务
内部方法会加入到外围方法的事务中,使用同一个事务,不管内外谁发生异常,整个事务都将回滚。
/**
* Support a current transaction; execute non-transactionally if none exists.
* Analogous to the EJB transaction attribute of the same name.
* <p><b>NOTE:</b> For transaction managers with transaction synchronization,
* {@code PROPAGATION_SUPPORTS} is slightly different from no transaction
* at all, as it defines a transaction scope that synchronization might apply to.
* As a consequence, the same resources (a JDBC {@code Connection}, a
* Hibernate {@code Session}, etc) will be shared for the entire specified
* scope. Note that the exact behavior depends on the actual synchronization
* configuration of the transaction manager!
* <p>In general, use {@code PROPAGATION_SUPPORTS} with care! In particular, do
* not rely on {@code PROPAGATION_REQUIRED} or {@code PROPAGATION_REQUIRES_NEW}
* <i>within</i> a {@code PROPAGATION_SUPPORTS} scope (which may lead to
* synchronization conflicts at runtime). If such nesting is unavoidable, make sure
* to configure your transaction manager appropriately (typically switching to
* "synchronization on actual transaction").
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#SYNCHRONIZATION_ON_ACTUAL_TRANSACTION
*/
int PROPAGATION_SUPPORTS = 1;
PROPAGATION_MANDATORY
mandatory是强制的意思,支持当前事务,如果没有事务,就抛出一个异常
外围方法未开启事务
抛出一个异常。
外围方法开启事务
内部方法会加入到外围方法的事务中,使用同一个事务,不管内外谁发生异常,整个事务都将回滚。
/**
* Support a current transaction; throw an exception if no current transaction
* exists. Analogous to the EJB transaction attribute of the same name.
* <p>Note that transaction synchronization within a {@code PROPAGATION_MANDATORY}
* scope will always be driven by the surrounding transaction.
*/
int PROPAGATION_MANDATORY = 2;
PROPAGATION_REQUIRES_NEW
不管当前是否存在事务,都创建一个新事务,如果存在事务,将当前事务暂停(挂起)
外围方法未开启事务
内部会创建新事务,若内部事务回滚,不影响外围方法。
外围方法开启事务
内部方法依然会单独开启独立事务,且与外部方法事务也独立,内部方法之间、内部方法和外部方法事务均相互独立,互不干扰。
代码验证REQUIRES_NEW事务传播机制
/**
* Create a new transaction, suspending 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 jakarta.transaction.TransactionManager} to be
* made available it to it (which is server-specific in standard Jakarta EE).
* <p>A {@code PROPAGATION_REQUIRES_NEW} scope always defines its own
* transaction synchronizations. Existing synchronizations will be suspended
* and resumed appropriately.
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
int PROPAGATION_REQUIRES_NEW = 3;
PROPAGATION_NOT_SUPPORTED
不支持事务,不管当前是否存在事务都以非事务方式执行。
外围方法未开启事务
以非事务方式执行。
外围方法开启事务
以非事务方式执行。
/**
* Do not support a current transaction; rather always execute non-transactionally.
* 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 jakarta.transaction.TransactionManager} to be
* made available it to it (which is server-specific in standard Jakarta EE).
* <p>Note that transaction synchronization is <i>not</i> available within a
* {@code PROPAGATION_NOT_SUPPORTED} scope. Existing synchronizations
* will be suspended and resumed appropriately.
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
int PROPAGATION_NOT_SUPPORTED = 4;
PROPAGATION_NEVER
不支持事务,如果存在事务,会抛出一个异常
外围方法未开启事务
以非事务方式执行。
外围方法开启事务
抛出一个异常。
/**
* Do not support a current transaction; throw an exception if a current transaction
* exists. Analogous to the EJB transaction attribute of the same name.
* <p>Note that transaction synchronization is <i>not</i> available within a
* {@code PROPAGATION_NEVER} scope.
*/
int PROPAGATION_NEVER = 5;
PROPAGATION_NESTED
如果存在当前事务,则在嵌套事务中执行,如果不存在事务,则和PROPAGATION_REQUIRED一样,会新建一个事务。
外围方法未开启事务
与Propagation.REQUIRED 作用相同,内部会创建新事务,若内部事务回滚,不影响外围方法。
外围方法开启事务
修饰的内部方法属于外部事务的子事务,外围主事务回滚,子事务一定回滚,而内部子事务可以单独回滚而不影响外围主事务和其他子事务。
/**
* Execute within a nested transaction if a current transaction exists,
* behave like {@link #PROPAGATION_REQUIRED} otherwise. There is no
* analogous feature in EJB.
* <p><b>NOTE:</b> Actual creation of a nested transaction will only work on
* specific transaction managers. Out of the box, this only applies to the JDBC
* {@link org.springframework.jdbc.datasource.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;
总结
required,有就加入,没有就自己动手
required_new,不求人,自己动手,丰衣足食,互不干扰
supports,有就加入,没有也无所谓。
not_supports,有我也不用。
never,必须没有,有了就抛异常。
mandatory 与 never是一对反义词,mandatory 是必须共用一个事物,否则就抛异常;而never必须无事务,有事务就抛异常。
nested,有就嵌套,没有就玩自己的,外部影响内部,内部不影响外部。