文章目录
- 1 简介
- 2 稍微更细致的介绍
- 2.1 第2、3、4种请自行验证
- 2.2 REQUIRES_NEW ---> 父级异常,它可正常提交
- 2.3 PROPAGATION_NESTED ---> 父级异常,它必然回滚;它异常,父级可以不回滚
- 2.4 PROPAGATION_NESTED和PROPAGATION_REQUIRED的区别
- 2.5 PROPAGATION_NESTED和REQUIRES_NEW的区别
1 简介
事务传播行为是什么???为啥会有事务传播行为???这个问题我觉得其实挺好回答的。
假设方法A调用方法B
- 方法A有事务,方法B可以什么不用管,直接拥有事务吗???
- 方法A有事务,方法B可以不使用事务吗?—> 也就是说方法B虽然报异常了,但方法B仍然可以将数据插入到数据库里?
- 方法A有事务,方法B可以有自己单独的事务吗? —> 比如方法B报异常了,只会导致方法B回滚,方法A不用回滚。
。。。。。
真实工作中需求总是千变万化,上面这些类似的需求说不定哪天我们就真的会遇到,其实这就是所谓的事务传播行为,spring确实是真优秀,人家不仅想到了类似的需求,还一下想到了7种 — 即7大传播行为。7大传播行为总结如下:
2 稍微更细致的介绍
2.1 第2、3、4种请自行验证
上图中第2、3、4种事务传播行为没有啥,有兴趣的可以clone下来我的代码自己测试一下。
github地址:https://github.com/nieandsun/spring-study
PROPAGATION_NEVER 和 PROPAGATION_NOT_SUPPORTED也比较简单,这里简单再提一下:
-
PROPAGATION_NEVER —> 如果方法A存在事务,方法A调用方法B,方法B为强制非事务,方法A调用了方法B,方法A会直接报错,并发生回滚。
-
PROPAGATION_NOT_SUPPORTED —> 如果方法A存在事务,方法A调用方法B,方法B为不支持事务 ,则方法B报异常,会导致方法A回滚,
但是方法B有可能会对数据库里的数据完成修改
。
2.2 REQUIRES_NEW —> 父级异常,它可正常提交
方法A存在事务,方法A(这里将方法A称为父级方法)调用方法B,方法B为REQUIRES_NEW时,方法B会新建一个新的事务,而不用方法A的事务,这样如果方法B没有异常,方法A调完方法B,方法A又报了异常,只会导致方法A进行回滚,而方法B可正常提交。
2.3 PROPAGATION_NESTED —> 父级异常,它必然回滚;它异常,父级可以不回滚
如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作很好理解。
如果当前存在事务,则在嵌套事务内执行,具体表现行为:
- 如果方法A(这里将方法A称为父级方法)存在事务,且方法A调用方法B,方法B为PROPAGATION_NESTED 时,A方法可以捕获B方法的异常,从而只让B方法发生回滚,而A不发生回滚。
并且假如方法A有事务,只要方法A发生了异常,方法B也肯定会回滚。
2.4 PROPAGATION_NESTED和PROPAGATION_REQUIRED的区别
以如下代码为例:
- UserServiceImpl中的方法
@Transactional(rollbackFor = Exception.class)
@Override
public void addUserAndSalary(String username, BigDecimal salary) {//按照生日等生成一个14位的员工编号String account = "20191218000001";//往员工表里插入该用户的用户信息userServiceDao.saveUserInfo(username, account);//往人资表里插入该用户的工资信息try {salaryService.addSalaryInfo(account, salary);System.err.println(111);}catch (Exception e){e.printStackTrace();}//int i = 1 / 0;
}
- SalaryServiceImpl中的方法
@Transactional(propagation = Propagation.XXXX, rollbackFor = Exception.class)
@Override
public void addSalaryInfo(String account, BigDecimal salary) {salaryDao.addSalaryInfo(account, salary);int i = 1 / 0;
}
如果addSalaryInfo方法标注的是PROPAGATION_NESTED时
- 子级方法会发生回滚 —>salary表里无法插入数据
- 父级方法会执行成功 —> user表里会插入数据
如果addSalaryInfo方法标注的是PROPAGATION_REQUIRED时
- 子级方法会发生回滚 —>salary表里无法插入数据
- 父级方法也会发生回滚 —>user表里无法插入数据
2.5 PROPAGATION_NESTED和REQUIRES_NEW的区别
以如下代码为例:
- UserServiceImpl中的方法
@Transactional(rollbackFor = Exception.class)@Overridepublic void addUserAndSalary(String username, BigDecimal salary) {//按照生日等生成一个14位的员工编号String account = "20191218000001";//往员工表里插入该用户的用户信息userServiceDao.saveUserInfo(username, account);//往人资表里插入该用户的工资信息try {salaryService.addSalaryInfo(account, salary);System.err.println(111);} catch (Exception e) {e.printStackTrace();}int i = 1 / 0;}
- SalaryServiceImpl中的方法
@Transactional(propagation = Propagation.XXXX, rollbackFor = Exception.class)
@Override
public void addSalaryInfo(String account, BigDecimal salary) {salaryDao.addSalaryInfo(account, salary);//int i = 1 / 0;
}
如果addSalaryInfo方法标注的是PROPAGATION_NESTED时
- 父级方法会发生回滚 —>user表里无法插入数据
- 子级方法也会发生回滚 —>salary表里无法插入数据
如果addSalaryInfo方法标注的是REQUIRES_NEW时
- 父级方法会发生回滚 —>user表里无法插入数据
- 子级方法不会发生回滚 —>salary表里会插入数据