spring事务的传播
关于事务的传播,我们先确定一个场景:方法A调用方法B,方法A可能存在事务,也可能不存在事务,我们这里重点关注方法B上定义的事务传播行为,以及方法B中出现异常时,方法A应该如何处理事务的提交或回滚(如果存在)。
@Autowired private ServiceB serviceB;
public void methodA() {
// do anything
serviceB.mehtodB();
// do anything
}
@Transactional(propagation = Propagation.NESTED)
public void mehtodB() {
// do anything
}
事务的传播行为类型
1 .PROPAGATION_REQUIRED(默认实现)
方法B的执行需要有事务,如果方法A有事务,那么方法B加入方法A的事务,方法A或B的异常都会导致整个事务回滚。
2 .PROPAGATION_SUPPORTS
方法B的执行支持事务,如果方法A存在事务,那么方法B加入方法A的事务,否则方法B以无事务的方式执行。此情景下,A方法事务回滚也将导致方法B回滚,方法A无事务则不影响。
3 .PROPAGATION_MANDATORY
方法B强制必须在事务条件下执行,方法B加入方法A的事务执行,如果方法A无事务,则抛出异常。
4 .PROPAGATION_REQUIRES_NEW
方法B必须在新事务中执行,如果A存在事务,那么把方法A的事务挂起;此种情境下,方法A和方法B的回滚不会影响到对方。
5 .PROPAGATION_NOT_SUPPORIED
方法B必须在无事务条件下执行,如果方法A存在事务,那么需要将方法A的事务挂起。
6 .PROPAGATION_NEVER
方法B必须在不存在事务的条件下执行,如果方法A存在事务,则抛出异常。
7 .PROPAGATION_NESTED
这里我们需要了解下嵌套事务的提交
- 我们把嵌套事务视作一棵树,根节点事务叫做顶层的事务,其它事务是顶层事务的子事务;
- 任何嵌套的子事务的提交和回滚,都必须在它的父事务提交后进行;嵌套的子事务可以独立于当前事务进行单独地提交或回滚;
- 任何父事务的回滚都会导致它的所有子事务的回滚。
嵌套事务,如果方法A存在事务,那么方法B的创建一个方法A事务的嵌套事务(从数据库的层面看,也可视为子事务),如果方法A不存在事务,那么行为与PROPAGATION_REQUIRED相同。
此处,父事务的回滚行为会导致子事务回滚;而子事务的回滚和提交独立于父事务。
注意事项
-
非public 方法会导致事务失效
-
事务默认的异常类型是: RuntimeException