Spring 事务传播行为

Spring特有的事务传播行为,Spring支持7种事务传播行为,确定客户端和被调用端的事务边界。即多个具有事务控制的service进行相互调用时所参生的复杂行为。下面对7种进行合理的分析和讲解。

事务传播行为含义
PROPAGATION_REQUIRED如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置
PROPAGATION_REQUIRED_NEW创建新事务,无论当前存不存在事务,都创建新事务
PROPAGATION_MANDATORY支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常
PROPAGATION_SUPPORTS支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行
PROPAGATION_NOT_SUPPORTED以非事务的方式执行,如果当前存在事务,就把当前事务挂起
PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常
PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

下面我将举例对这七种行为进行复现。并根据结果进行分析。

环境:Spring-boot + Mysql 

创建实例类 Admin :

public class Admin {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Column(nullable = false)
    private String name;
    @Column(nullable = false)
    private String password;
    @Enumerated(EnumType.STRING)
    private AdminType type;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public AdminType getType() {
        return type;
    }

    public void setType(AdminType type) {
        this.type = type;
    }
}

1. PROPAGATION_REQUIRED 

创建事务function和,事务的测试function

@Transactional(propagation = Propagation.REQUIRED)
    public void transactionTest(){
        Admin admin=new Admin();
        admin.setType(AdminType.管理员);
        admin.setName("test");
        admin.setPassword("123");
        adminRepository.save(admin);
        throw new RuntimeException("error");
    }

    @Test
    public void testTransaction(){
        adminService.transactionTest();
      
    }

执行testTransaction函数。发现抛出异常,数据里面没有添加新的数据。证明按照了事务的方式在执行函数。

2.PROPAGATION_REQUIRED_NEW

修改transactionTest 和 testTransaction函数如下

     @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void transactionTest(){
        Admin admin=new Admin();
        admin.setType(AdminType.管理员);
        admin.setName("test");
        admin.setPassword("123");
        adminRepository.save(admin);


    }

    @Test
    @Transactional()
    public void testTransaction(){
        adminService.transactionTest();
        throw new RuntimeException("Error");
    }

在testTransaction函数里面抛出异常。结果是数据库正常的存入数据了。证明是transactionTest函数又自己创建了一个事务。与外层的事务没有关系。外层事务的回滚不影响到内层事务的正常执行。

3.PROPAGATION_MANDATORY

修改transactionTest和testTransaction函数如下:

@Transactional(propagation = Propagation.MANDATORY)
public void transactionTest(){
    Admin admin=new Admin();
    admin.setType(AdminType.管理员);
    admin.setName("test");
    admin.setPassword("123");
    adminRepository.save(admin);
}
@Test
public void testTransaction(){
    adminService.transactionTest();
    throw new RuntimeException("Error");
}

运行直接抛出异常如下:

org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'

表面Mandatory必须要存在事务才能调用,不然就直接抛出异常。

4.PROPAGATION_SUPPORTS

修改函数如下:

@Test
public void testTransaction(){
    adminService.transactionTest();
   
}
@Transactional(propagation = Propagation.SUPPORTS)
public void transactionTest(){
    Admin admin=new Admin();
    admin.setType(AdminType.管理员);
    admin.setName("test");
    admin.setPassword("123");
    adminRepository.save(admin);
    throw new RuntimeException("Error");
}

执行结果,抛出异常,但是数据还是存储到了数据库。说明在调用方没有事务的情况下,按照没有事务执行。

5.PROPAGATION_NOT_SUPPORTED

修改函数如下:

@Test
@Transactional
public void testTransaction(){
    adminService.transactionTest();

}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void transactionTest(){
    Admin admin=new Admin();
    admin.setType(AdminType.管理员);
    admin.setName("test");
    admin.setPassword("123");
    adminRepository.save(admin);
    throw new RuntimeException("Error");
}

运行结果如下,抛出异常。数据存入到数据库。说明调用方就算是有事务,被调用方依旧按照非事务的方式在执行。

6.PROPAGATION_NEVER

@Test
@Transactional
public void testTransaction(){
    adminService.transactionTest();

}
@Transactional(propagation = Propagation.NEVER)
public void transactionTest(){
    Admin admin=new Admin();
    admin.setType(AdminType.管理员);
    admin.setName("test");
    admin.setPassword("123");
    adminRepository.save(admin);
   
}
直接排除异常,不支持事务。
org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'

7.PROPAGATION_NESTED

修改函数如下:

@Test
@Transactional
public void testTransaction(){
    adminService.transactionTest();

}
@Transactional(propagation = Propagation.NESTED)
public void transactionTest(){
    Admin admin=new Admin();
    admin.setType(AdminType.管理员);
    admin.setName("test");
    admin.setPassword("123");
    adminRepository.save(admin);
    throw new RuntimeException("Error");
}

运行结果:抛出异常,数据没有存入到数据库。证明是按照事务的方式进行执行的。

总结:7种事务的传播行为都做了一个小的demo。可以很简单的帮助理解Spring事务的每个传播机制。只有合理和深入的了解了Spring的传播机制才能真正写出更加优秀和合理的代码。






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值