Spring事务的七种传播行为
事务传播行为类型 | 说明 |
---|---|
PROPAGATION_REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
本篇文档主要以 PROPAGATION_REQUIRED PROPAGATION_REQUIRES_NEW两个传播行为讲解
PROPAGATION_REQUIRED此传播行为为Spring默认的传播行为
使用到的实体类 Order1 及Order2
public class Order01 {
private int id;
private String orderNo;
//set get 构造函数等省略
}
表结构
order1的Service业务方法
@Autowired
private Order1Mapper order1Mapper;
@Transactional(propagation = Propagation.REQUIRED)
public void addOrder1() {
Order01 order01=new Order01();
order01.setId(1);
order01.setOrderNo("order010401");
System.out.println("Order01进入");
System.out.println(order01);
order1Mapper.insert(order01);
}
@Transactional(propagation = Propagation.REQUIRED)
public void addOrder1Exception() {
Order01 order01=new Order01();
order01.setId(2);
order01.setOrderNo("order010401");
order1Mapper.insert(order01);
throw new RuntimeException();
}
1.测试 PROPAGATION_REQUIRED
测试代码如下
public void runOrder(){
order1Service.addOrder1();
order1Service.addOrder1Exception();
}
addOrder1没有出现异常 addOrder1Exception 手动抛出了一个RuntimeException异常
两个方法都由@Transactional注解修饰
此时执行结果为
addOrder1 | addOrder1Exception |
执行成功 | 执行失败抛出异常,事务回滚 |
按照我们意愿来想 addOrder1与addOrder1Exception 两个方法 要么全部成功,要么全部不成功
所以在runOrder此方法上加上注解@Transactional(propagation = Propagation.REQUIRED)
此时执行结果为
addOrder1 | addOrder1Exception |
执行失败 | 执行失败 |
由于runOrder的@Transactional(PROPAGATION_REQUIRED)指代
如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。 |
所以此时addOrder 与addOrderException的事务都统一由runOder的事务去管理
及以前是 a b 两个小事务 各管各的,现在由C这个事务去管理,a b c 中只要一个地方出现异常 该事务就回滚;
2.测试 PROPAGATION_REQUIRES_NEW
修改order1Service的具体实现逻辑
@Autowired
private Order1Mapper order1Mapper;
@Transactional(propagation = Propagation.REQUIRED)
public void addOrder1REQUIRED() {
Order01 order01=new Order01();
order01.setId(1);
order01.setOrderNo("order010401");
order1Mapper.insert(order01);
throw new RuntimeException();
}
@Transactional(propagation = Propagation.REQUIRED)
public void addOrder1ExceptionREQUIRED() {
Order01 order01=new Order01();
order01.setId(2);
order01.setOrderNo("order010401");
order1Mapper.insert(order01);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void addOrder01REQUIRES_NEW() {
Order01 order01=new Order01();
order01.setId(3);
order01.setOrderNo("order010401");
order1Mapper.insert(order01);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void addOrder01REQUIRES_NEWException() {
Order01 order01=new Order01();
order01.setId(4);
order01.setOrderNo("order010401");
order1Mapper.insert(order01);
throw new RuntimeException();
}
在原有逻辑的基础上,修改了方法名,增加了两个方法
.addOrder01REQUIRES_NEW
addOrder01REQUIRES_NEWException
新增的两个方法的事务传播行为都为 PROPAGATION_REQUIRES_NEW
寓意挂起当前事务,重启一个事务
此时执行runOrder方法
@Transactional(propagation = Propagation.REQUIRED)
public void runOrder(){
order1Service.addOrder01REQUIRES_NEW();
order1Service.addOrder1REQUIRED();
order1Service.addOrder1ExceptionREQUIRED();
order1Service.addOrder01REQUIRES_NEWException();
}
执行结果如下
addOrder01REQUIRES_NEW | 执行成功 |
addOrder1REQUIRED | 执行失败 |
addOrder1ExceptionREQUIRED | 执行失败 |
addOrder01REQUIRES_NEWException | 执行失败 |
addOrder1REQUIRED addOrder1ExceptionREQUIRED执行失败原因:
这两个方法的事务都是有runOrder方法的事务去管理 只要这三个方法有一个地方出现异常 这三个地方都会回滚
addOrder01REQUIRES_NEW 执行成功原因:
此方法的传播行为 寓意 重新启动一个事务 该事务与runOrder事务无关,该事务无论成功与否都不会影响runOrder事务的提交或回滚
addOrder01REQUIRES_NEWException执行失败原因:
此方法新建一个事务,该事务与runOrder事务无关,执行失败只回滚当前事务,不会影响runOrder事务的执行,所以他失败回滚了;
3.PROPAGATION_NESTED(事务嵌套)
日后补充....
学而不思则罔,思而不学则殆。