事务的嵌套使用,你真的掌握了吗?

本文详细解析了Spring框架中的事务传播机制,包括不同传播行为的含义及其应用场景,并通过实例演示了各种情况下事务如何进行回滚。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

spring事务传播机制

传播行为含义回滚机制
PROPAGATION_REQUIRED_NEW表示当前方法必须运行在自己的事务中,会启动一个新的事务,如果存在当前事务,在执行期间就会挂起当前事务。A->B B报错仅回滚B A报错与B无关
PROPAGATION_NEVER表示当前方法不应该运行在事务上下文中,如果当前有事务运行,会直接抛异常。A->B 若A有事务,B压根不会执行(抛异常)
PROPAGATION_MANDATORY表示该方法必须在事务中运行,如果当前事务不存在,就直接抛异常。A->B 若A无事务,B压根不会执行(抛异常)
PROPAGATION_REQUIRED这是默认的传播行为。表示当前方法必须运行在事务中,如果当前事务存在,就直接使用这个事务,否则,开启一个新的事务。简单地说就是,如果存在事务,就用该事务,否则就创建一个事务拿来用。A->B 若A没有事务,则B新建一个事务,B报错不会导致A回滚 若A有事务,则B加入到A事务,为同一个事务,A、B报错A、B都会回滚
ROPAGATION_SUPPORTED表示当前方法不需要事务上下文,但如果存在当前事务的话,那么就在这个事务中执行。简单地说,如果存在事务就用,不存在事务就非事务执行。可以大体理解为:这个注解相当于没加
PROPAGATION_NOT_SUPPORTED表示该方法不应该运行在事务中,如果存在当前事务,那么在方法运行期间,会直接挂起当前事务。可以大体理解为:这个注解相当于,注意与REQUIRED区别
PROPAGATION_NESTED表示如果当前已存在一个事务,那么该方法会嵌套在事务中运行,嵌套的事务可以独立于当前事务单独提交或回滚;如果当前不存在事务,那么就与PROPAGATION_REQUIRED一样。父事务报错会导致子事务回滚 子事务报错父事务不一定回滚(有没有catch,有catch外层不回滚,里层回滚)

使用误区
疑问点验证
1.调用者存在事务,被调用者无事务注解且抛出异常,会回滚吗?

代码块
SQL

@Transactional(propagation = Propagation.REQUIRED)
    public void insert() {
        aMapper.insert(new A());
        System.out.println("insert a");
        b.insert();
    }
 
 public void insert() {
        bMapper.insert(new B());
        System.out.println("insert b");
        throw new RuntimeException();
    }
    

揭晓答案
A、B都会回滚

2.调用者存在事务,被调用者无事务注解并且抛出异常且被调用者捕获,会回滚吗?

代码块
SQL

@Transactional(propagation = Propagation.REQUIRED)
    public void insertA() {
        aMapper.insert(new A());
        System.out.println("insert a");
        try {
            b.insertB();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
  public void insert() {
        bMapper.insert(new B());
        System.out.println("insert b");
        throw new RuntimeException();
    }

揭晓答案
A、B都不会回滚
3.调用者无事务注解,被调用者存在事务并且抛出异常会回滚吗?

代码块
SQL

public void insertA() {
        aMapper.insert(new A());
        System.out.println("insert a");
        b.insertB();
    }
    
 @Transactional(propagation = Propagation.REQUIRED)
    public void insertB() {
        bMapper.insert(new B());
        System.out.println("insert b");
        throw new RuntimeException();
    }

揭晓答案
A不回滚,B回滚

4.调用者和被调用者都是REQUIRED,被调用者抛出异常,而调用者捕获异常,会回滚吗?

代码块
SQL

@Transactional(propagation = Propagation.REQUIRED)
    public void insertA() {
        aMapper.insert(new A());
        System.out.println("insert a");
        try {
            b.insertB();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }@Transactional(propagation = Propagation.REQUIRED)
    public void insertB() {
        bMapper.insert(new B());
        System.out.println("insert b");
        throw new RuntimeException();
    }

揭晓答案
AB都回滚

5.调用者REQUIRED,被调用者是NESTED,被调用者抛出异常,而调用者捕获异常,会回滚吗?

代码块
SQL

@Transactional(propagation = Propagation.REQUIRED)
    public void insertA() {
        aMapper.insert(new A());
        System.out.println("insert a");
        try {
            b.insertB();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
  @Transactional(propagation = Propagation.NESTED)
    public void insertB() {
        bMapper.insert(new B());
        System.out.println("insert b");
        throw new RuntimeException();
    }

揭晓答案
A不回滚、B回滚

在这里插入图片描述
答案:a、b都不回滚

结论:如果当前函数中主动捕获异常就不会回滚,如果被spring捕获就回滚

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值