8个示例详解 Spring 事务传播机制(附测试源码)

什么是事务传播机制

事务的传播机制,顾名思义就是多个事务方法之间调用,事务如何在这些方法之间传播。

举个例子,方法 A 是一个事务的方法,方法 A 执行的时候调用了方法 B,此时方法 B 有无事务以及是否需要事务都会对方法 A 和方法 B 产生不同的影响,而这个影响是由两个方法的事务传播机制决定的。

传播属性 Propagation 枚举

Spring 对事务的传播机制在 Propagation 枚举中定义了7个分类:

  • REQUIRED 默认
  • SUPPORTS 支持
  • MANDATORY 强制
  • REQUIRES_NEW 新建
  • NOT_SUPPORTED 不支持
  • NEVER 从不
  • NESTED 嵌套

事务的传播机制,是 spring 规定的。因为在开发中,最简单的事务是,业务代码都处于同一个事务下,这也是默认的传播机制,如果出现的报错,所有的数据回滚。

但是在处理复杂的业务逻辑时,方法之间的调用,有以下的需求:

  • 调用的方法需要新增一个事务,新事务和原来的事务各自独立。
  • 调用的方法不支持事务
  • 调用的方法是一个嵌套的事务

7种传播机制详解

首先创建两个方法 A 和 B 实现数据的插入,插入数据A:

public class AService {
    public void A(String name) {
        userService.insertName("A-" + name);
    }

}

插入数据B:

public class BService {
    public void B(String name) {
        userService.insertName("B-" + name);
    }

}

使用伪代码创建 mainTest 方法和 childTest 方法

public void mainTest(String name)  {
        // 存入a1
        A(a1);
        childTest(name);
    }

main 调用 test 方法,其中

public void childTest(String name)  {
        // 存入b1
        B(b1);
       throw new RuntimeException(); 
       // 存入 b2
       B2(b2);
    }

以上伪代码,调用 mainTest 方法,如果mainTest 和childTest 都不使用事务 的话,数据存储的结果是如何呢?

因为都没使用事务,所以 a1 和 b1 都存到成功了,而之后抛出异常之后,b2是不会执行的。所以 a1 和 b1 都插入的数据,而 b2 没有插入数据。

REQUIRED(默认事务)

/**
	 * Support a current transaction, create a new one if none exists.
	 * Analogous to EJB transaction attribute of the same name.
	 * <p>This is the default setting of a transaction annotation.
	 */
	REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),

如果当前不存在事务,就新建一个事务。如果存在事务,就加入到当前事务。这是一个默认的事务。

示例1:根据场景举个例子,在 childTest 添加事务,设置传播属性为 REQUIRED,伪代码如下:

public void mainTest(String name)  {
        // 存入a1
        A(a1);
        childTest(name);
    }
   @Transactional(propagation = Propagation.REQUIRED)
   public void childTest(String name)  {
        // 存入b1
        B(b1);
       throw new RuntimeException(); 
    }

因为 mainTest 没有事务,而 childTest 又是新建一个事务,所以 a1 添加成功。在 childTest 因为抛出了异常,不会执行 b2 添加,而 b1 添加回滚。最终 a1 添加成功,b1没添加成功。

示例2:在 mainTest 和 childTest 都添加事务,传播属性都为 REQUIRED,伪代码如下:

@Transactional(propagation = Propagation.REQUIRED)
   public void mainTest(String name) {
        // 存入a1
        A(a1);
        childTest(name);
    }
   @Transactional(propagation = Propagation.REQUIRED)
   public void childTest(String name) {
        // 存入b1
        B(b1);
       throw new RuntimeExce
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值