spring 事务传播性

时间:2021-09-15
本文章向大家介绍spring 事务传播性,主要包括spring 事务传播性使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一.什么是事务传播性

   大白话讲就是,方法之间互相调用的时候,事务如何传播,比如A()调用B(),B()的事务是和A()共用一个事务(失败一起提交)?

还是新事务(两者事务互不影响)?,还是说B()不需要事务?,这就是事务传播性的意思。

    @Transactional()
    public void methodA(){
        methodB();
        //doSomething
    }

    @Transactional()
    public void methodB(){
        //doSomething
    }

  代码中的methodB()默认的传播性是REQUIRED,表示和methodA共用一个事务,要提交一起提交,要失败一起回滚。

二.spring中几种事务传播性

事务传播性 说明
REQUIRED 默认传播性,如果当前有事务,就沿用当前事务,如果没有就新建一个事务
SUPPORTS 支持当前事务,如果当前没有事务,就以非事务运行
REQUIRES_NEW 新建一个事务,如果当前存在事务,就把当前事务挂起
NOT_SUPPORTED 不支持事务,如果当前存在事务,就把当前事务挂起。
MANDATORY 强制使用当前事务,如果当前没有事务就抛异常
NEVER 以非事务方式运行,如果当前存在事务,则抛出异常
NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

三.举例说明

1.REQUIRED

说明:支持当前事务,如果当前没有事务就新建一个事务

insertUser()和insertStu是共用一个事务,要提交一起提交要失败一起失败。

@Transactional(propagation = Propagation.REQUIRED)
public void insertUser(String name) {
    User user = new User();
    user.setName(name);
    userDao.insertUser(user);
    stuService.insertStu(name);
}
stuService中
@Transactional(propagation = Propagation.REQUIRED)
public void insertStu(String name){
        Stu stu = new Stu();
        stu.setName(name);
        stuDao.insertUser(stu);
        //这个地方发生异常,会引起insertStu也回滚,说明两者的事务是同一个
        throw new RuntimeException();
}

2.REQUIRES_NEW

说明:开启新的事务,如果当前存在事务,就挂起当前事务。

insertUser()的失败回滚,不会导致insertStu的回滚,因为insertStu()在一个新的事务中。

@Transactional(propagation = Propagation.REQUIRED)
public void insertUser(String name) {
    User user = new User();
    user.setName(name);
    userDao.insertUser(user);
    stuService.insertStu(name);
    throw new RuntimeException();
}
//上面的方法抛异常事务的回滚,不会导致下面事务回滚,stu插入成功,user插入失败
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void insertStu(String name){
        Stu stu = new Stu();
        stu.setName(name);
        stuDao.insertUser(stu);

}

3.SUPPORTS

说明:如果当前已经存在事务,那么加入该事务,否则创建一个所谓的空事务(可以认为无事务执行)

insertUser是以非事务运行的,所以insertStu也是没有事务的,所以两个保存都会成功

但是如果给inertStu加上@Transactional(propagation = Propagation.REQUIRED)insertStu是有事务的。

    public void insertUser(String name) {
        User user = new User();
        user.setName(name);
        userDao.insertUser(user);
        stuService.insertStu(name);
        throw new RuntimeException();
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public void insertStu(String name){
        Stu stu = new Stu();
        stu.setName(name);
        stuDao.insertUser(stu);
    }

4.NOT_SUPPORTED

说明:不支持事务,如果当前存在事务,挂起当前事务,然后新的方法在没有事务的环境中执行

下面的insertUser会回滚,insertStu将以非事务运行,所以不会回滚

这种的业务场景可能是,日志写入事务要和主事务隔离,外层事务写入失败,不影响日志的写入。

@Transactional(propagation = Propagation.REQUIRED)
public void insertUser(String name) {
    User user = new User();
    user.setName(name);
    userDao.insertUser(user);
    stuService.insertStu(name);
    throw new RuntimeException();
}

 @Transactional(propagation = Propagation.NOT_SUPPORTED)
 public void insertStu(String name){
        Stu stu = new Stu();
        stu.setName(name);
        stuDao.insertUser(stu);
 }

 5.MANDATORY

说明:当前必须存在一个事务,否则抛出异常。

因为insertUser()没有配置事务,所以insertStu()会报错。

异常信息:No existing transaction found for transaction marked with propagation 'mandatory'

public void insertUser(String name) {
    User user = new User();
    user.setName(name);
    userDao.insertUser(user);
    stuService.insertStu(name);
    throw new RuntimeException();
}
 @Transactional(propagation = Propagation.MANDATORY)
    public void insertStu(String name){
        Stu stu = new Stu();
        stu.setName(name);
        stuDao.insertUser(stu);
 }

6.NEVER

说明:不支持事务,如果当前存在事务,就抛出异常。

因为insertUser()配置了事务,所以在insertStu中会报错。

异常信息:Existing transaction found for transaction marked with propagation 'never'

@Transactional(propagation = Propagation.REQUIRED)
public void insertUser(String name) {
    User user = new User();
    user.setName(name);
    userDao.insertUser(user);
    stuService.insertStu(name);
    //throw new RuntimeException();
}

@Transactional(propagation = Propagation.NEVER)
public void insertStu(String name){
     Stu stu = new Stu();
     stu.setName(name);
     stuDao.insertUser(stu);
}

7.NESTED

说明:NESTED修饰的内部方法属于外部事务的子事务,外围主事务回滚,子事务一定回滚,而内部子事务可以单独回滚而不影响外围主事务和其他子事务

主要的场景可能是,下单的时候,送积分,如果下单失败,送积分也要回滚,但送积分失败不影响下单失败。这种场景可以使用这种传播性

原文地址:https://www.cnblogs.com/jack1990/p/15266877.html