我们日常工作中极少使用事务传播级别,单纯只是使用事务和rollbackfor抛出异常来解决事务问题,但其实我们很多时候使用的是不正确的,或者说会造成事务粒度过大,本文详解一下事务传播级别,也让自己更好地处理事务问题。
1. Spring事务传播机制
1.什么是事务传播机制?
举个栗子,方法A是一个事务的方法,方法A执行过程中调用了方法B,那么方法B有无事务以及方法B对事务的要求不同都会对方法A的事务具体执行造成影响,同时方法A的事务对方法B的事务执行也有影响,这种影响具体是什么就由两个方法所定义的事务传播类型所决定。
简单说就是,我们方法调用通常是,一个方法调用另外一个,而不同方法可以有不同的事务,所以传播机制就是指在多个方法,事务要如何传播。
2.Spring事务传播类型Propagation介绍
一共有七种传播类型
- Propagation.REQUIRED
- Propagation.SUPPORTS
- Propagation.MANDATORY
- Propagation.REQUIRED_NEW
- Propagation.NOT_SUPPORTED
- Propagation.NESTED
- Propagation.NEVER
本文从案例结合解释一下不同传播类型下多个@Transactional方法会发生什么?在遇到异常情况下,不同传播机制会产生什么影响。
1. Propagation.REQUIRED
这是默认的传播机制,我们最常用的一种,也是@Transactional默认的一种
如果当前没有事务,则自己新建一个事务,如果当前存在事务,则加入这个事务
// 示例1:
@Transactional(propagation = Propagation.REQUIRED)
public void main(){
insertA(); // 插入A
service.sub(); // 调用其他方法
}
// 两个Service中调用,如果同一个要注意不能用this调用,事务不会起作用
@Transactional(propagation = Propagation.REQUIRED)
public void sub(){
insertB(); //插入B
throw RuntimeException; //发生异常抛出
insertC(); //调用C
简单来说就是,开启一个事务,上面的案例就是当main方法如果没开启事务,那么sub方法就会开启,如果main方法已经@Transactional开启了事务,sub方法就会加入外层方法的事务,所以上面方法执行在遇到异常时候会全部回滚
结果:
A、B、C全部无法插入。
// 示例2:
public void main(){
insertA(); // 插入A
service.sub(); // 调用其他方法
}
// 两个Service中调用,如果同一个要注意不能用this调用,事务不会起作用
@Transactional(propagation = Propagation.REQUIRED)
public void sub(){
insertB(); //插入B
throw RuntimeException; //发生异常抛出
insertC(); //调用C
结果:
A插入成功,BC开启新的事务,遇到异常回滚,B、C无法插入
2. Propagation.SUPPORTS
当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行
// 示例3:
public void main(){
insertA(); // 插入A
service.sub(); // 调用其他方法
}
// 两个Service中调用,如果同一个要注意不能用this调用,事务不会起作用
@Transactional