spring事务的传播行为

spring事务的传播行为

一、事务的传播行为分类

根据 spring 源码中 org.springframework.transaction.annotation.Propagation 枚举类中的定义,总共有 7 中传播行为:

传播行为分类说明
REQUIRED(默认的传播行为)1、使用当前事务,如果当前没有事务,会新建一个事务
2、子方法也会运行在父方法的事务中,如果子方法存在事务,则会加入父方法的事务中
SUPPORTS当前存在事务,就使用事务;当前不存在事务,就不使用
MANDATORY当方法的事务传播行为设置为 MANDATORY 时,其它任何方法调用该方法时,都必须存在事务,否则抛出异常
REQUIRES_NEW1、如果当前有事务,挂起当前事务,新建一个事务给自己使用
2、如果当前没有事务,则新建一个事务
NOT_SUPPORTED不管当前有无事务,都不使用事务
NEVER不使用事务,如果调用方当前存在事务,抛出异常
NESTED如果当前有事务,则开启子事务(属于嵌套事务),嵌套事务是独立提交或者回滚的

二、简要示例

下面通过一些伪代码,来描述几种常用的传播行为:

REQUIRED

1、父方法中不存在事务,子方法中也不存在事务

class parentClass {
  // 父方法没有事务
  void parentMethod(){
      // 父方法中调用子方法
      subClass.subMethod();
      ...
  }
}

class subClass {
  // 子方法中也没有事务
  void subMethod(){
      ...
  }
}

这种情况下,出现异常之后,子父方法中的数据都不会回滚

2、父方法中存在事务,子方法中不存在事务

class parentClass {
  // 父方法存在事务
  @Transactional(propagation = Propagation.REQUIRED)
  void parentMethod(){
      // 父方法中调用子方法
      subClass.subMethod();
      ...
  }
}

class subClass {
  // 子方法中没有事务
  void subMethod(){
      ...
  }
}

这种情况下,父方法的事务会传递到子方法中,所以子父方法中只要出现异常,都会回滚数据

3、父方法中不存在事务,子方法中存在事务

class parentClass {
  // 父方法中不存在事务
  void parentMethod(){
      // 父方法中调用子方法
      subClass.subMethod();
      ...
  }
}

class subClass {
  // 子方法中存在事务
  @Transactional(propagation = Propagation.REQUIRED)
  void subMethod(){
      ...
  }
}
  • 这种情况下,如果子方法中出现异常,子方法中的数据会回滚,但是父方法中的数据不会回滚
  • 如果是子方法执行完成后,父方法出现异常,这时子方法的数据不会回滚,因为事务已经提交。父方法的数据也不会回滚,因为父方法没有事务

4、父方法中存在事务,子方法中也存在事务

class parentClass {
  // 父方法中存在事务
  @Transactional(propagation = Propagation.REQUIRED)
  void parentMethod(){
      // 父方法中调用子方法
      subClass.subMethod();
      ...
  }
}

class subClass {
  // 子方法中也存在事务
  @Transactional(propagation = Propagation.REQUIRED)
  void subMethod(){
      ...
  }
}

这种情况下,子方法会加入到父方法的事务中,所以子父方法中只要出现异常,都会回滚数据


MANDATORY

1、父方法不存在事务

class parentClass {
  // 父方法中不存在事务
  void parentMethod(){
      // 父方法中调用子方法
      subClass.subMethod();
      ...
  }
}

class subClass {
  // 子方法中存在事务
  @Transactional(propagation = Propagation.MANDATORY)
  void subMethod(){
      ...
  }
}

这种情况下,父方法在调用子方法时,会直接抛出异常,因为父方法没有事务

2、父方法存在事务

class parentClass {
  // 父方法中存在事务
  @Transactional(propagation = Propagation.REQUIRED)
  void parentMethod(){
      // 父方法中调用子方法
      subClass.subMethod();
      ...
  }
}

class subClass {
  // 子方法中也存在事务
  @Transactional(propagation = Propagation.MANDATORY)
  void subMethod(){
      ...
  }
}

这种情况下,父方法调用子方法时,是存在事务的,所以不会抛出异常。此时父方法的事务会传递到子方法中,所以只要是子父方法中出现异常,都会回滚数据


REQUIRES_NEW

1、父方法中不存在事务

class parentClass {
  // 父方法中不存在事务
  void parentMethod(){
      // 父方法中调用子方法
      subClass.subMethod();
      ...
  }
}

class subClass {
  // 子方法中存在事务
  @Transactional(propagation = Propagation.REQUIRES_NEW)
  void subMethod(){
      ...
  }
}

这种情况下,如果子方法出现异常,子方法的数据会回滚。父方法中的数据不会回滚

2、父方法中存在事务

class parentClass {
  // 父方法中存在事务
  @Transactional(propagation = Propagation.REQUIRES)
  void parentMethod(){
      // 父方法中调用子方法
      subClass.subMethod();
      ...
  }
}

class subClass {
  // 子方法中存在事务
  @Transactional(propagation = Propagation.REQUIRES_NEW)
  void subMethod(){
      ...
  }
}

这种情况下,需要注意:

  • 如果子方法中出现了异常,子方法的数据会回滚,子方法的异常会传递到父方法中,父方法的数据也会回滚掉
  • 如果子方法中没有出现异常,但是父方法在执行完子方法后,出现了异常,这时只会回滚父方法的数据,子方法的数据不会回滚,因为子方法的事务已经提交

NESTED

重点说下 NESTED 和 REQUIRED 的区别:
REQUIRES传播行为
NESTED传播行为

伪代码演示如下:

1、子父方法都是 Propagation.REQUIRED

class ParentClass {
    @Transactional(propagation = Propagation.REQUIRED)
    public void parentMethod() {
      // 父方法插入数据  
      stuMapper.insertSelective("父方法插入数据");
      // 调用子方法
      subClass.subMethod();
    }
}

class SubClass {
    @Transactional(propagation = Propagation.REQUIRED)
    public void subMethod() {
        // 插入数据
        stuMapper.insertSelective("子方法插入数据");
        int i = 1 / 0;
    }
}

这种情况下,subMethod() 会加入到 parentMethod() 的事务中去,如果 subMethod() 出现异常,则会直接回滚掉整个事务

2、子方法是 Propagation.NESTED

class ParentClass {
    @Transactional(propagation = Propagation.REQUIRED)
    public void parentMethod() {
      // 父方法插入数据  
      stuMapper.insertSelective("父方法插入数据");
      // 调用子方法
      try {
          // 调用subMethod()方法时,开启了一个嵌套事务,如果subMethod()出现异常,不会回滚parentMethod()的事务,嵌套事务独立回滚
          subClass.subMethod();
      } catch (Exception e) {
          // 打印日志
      }
      // 继续执行其它方法
    }
}

class SubClass {
    @Transactional(propagation = Propagation.NESTED)
    public void subMethod() {
        // 插入数据
        stuMapper.insertSelective("子方法插入数据");
        int i = 1 / 0;
    }
}

这种情况下,subMethod()开启了一个嵌套事务,如果subMethod()出现异常,不会回滚parentMethod()的事务,因为嵌套事务会独立回滚。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring框架中,事务传播行为用于定义一个方法调用时如何参与到已存在的事务中,或者如何创建一个新的事务Spring框架提供了多种事务传播行为选项,可以通过@Transactional注解或者编程式事务管理来配置。 以下是一些常见的Spring事务传播行为: 1. REQUIRED(默认):如果当前存在事务,则加入该事务;如果没有事务,则创建一个新的事务。这是最常用的传播行为,适合大多数情况。 2. SUPPORTS:如果当前存在事务,则加入该事务;如果没有事务,则以非事务的方式执行。适用于不需要强制要求事务的场景。 3. MANDATORY:如果当前存在事务,则加入该事务;如果没有事务,则抛出异常。适用于必须在一个已存在的事务中执行的场景。 4. REQUIRES_NEW:创建一个新的事务,并挂起当前的事务(如果存在)。适用于需要独立的事务执行的场景。 5. NOT_SUPPORTED:以非事务的方式执行操作,挂起当前的事务(如果存在)。适用于不需要事务支持的场景。 6. NEVER:以非事务的方式执行操作,如果当前存在事务,则抛出异常。适用于必须在没有事务的环境下执行的场景。 7. NESTED:如果当前存在事务,则在嵌套事务中执行;如果没有事务,则创建一个新的事务。嵌套事务是独立于外部事务的内部事务,它可以独立地进行提交或回滚,但是如果外部事务回滚,嵌套事务也会回滚。 通过选择合适的事务传播行为,可以确保在不同的方法调用中有效地管理事务,保证事务的一致性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值