首页 > 编程学习 > 【spring事务前置知识】事务的七大传播行为

文章目录

  • 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)
    @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时

  • 父级方法会发生回滚 —>user表里无法插入数据
  • 子级方法也会发生回滚 —>salary表里无法插入数据

如果addSalaryInfo方法标注的是REQUIRES_NEW时

  • 父级方法会发生回滚 —>user表里无法插入数据
  • 子级方法不会发生回滚 —>salary表里会插入数据
Copyright © 2010-2022 ngui.cc 版权所有 |关于我们| 联系方式| 豫B2-20100000