Spring事务传播机制

回顾

在这里插入图片描述

之前我们学习了Spring如何进行事务的实现和运用,今天我们来学习Spring事务的传播机制

简单介绍

Spring事务的传播机制就是当存在多个事务的时候,且多个事务方法存在调用关系,事务是如何在这些方法中进行传播的

事务的传播机制有哪些

@Transactional注解支持事务传播机制的设置,通过propagation属性来指定传播行为,
以A方法调用B方法为例,A⽅法运⾏时, 会开启⼀个事务. 当A调⽤B时, B⽅法本⾝也有事务, 此时B⽅法运⾏时, 是加⼊A的事务, 还是创建⼀个新的事务呢(使用自己的事务)?这个就涉及到了事务的传播机制.
Spring事务传播有以下七种机制:

Propagation.REQUIRED

默认的事务传播级别. 无论外层是否有事务,内层都需要有事务,外层没有就为自己新建事务,外层有就融入到外层的事务中

Propagation.SUPPORTS

外层没有事务,内层也不需要事务,外层有事务,内存就融入外层事务

Propagation.MANDATORY

要求外层必须有事务,且将内存融入到外层事务中,否则报错

Propagation.REQUIRES_NEW

无论外层是否有事务,内层都有事务,如果外层有事务,不会融入外层,而是自己新建事务,内外相互独立(日志记录)

Propagation.NOT_SUPPORTED

无论外层是否有事务,内层都不使用事务

Propagation.NEVER

外层存在事务,内层会抛出异常

Propagation.NESTED

无论外层是否有事务,内层都需要有事务,外层没有就为自己新建事务,外层有就融入到外层的事务中
与require的区别:nested隔离级别的内层出现异常,外层不会出现影响

实例

上面其中机制,我们只需要重点掌握两个:
REQUIRED
REQUIRES_NEW

REQUIRED

@RestController
public class PropagationController {
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private LogInfoService logInfoService;
    @Transactional( propagation = Propagation.REQUIRED)
    @RequestMapping("/insertInfo")
    public void insertInfo(String userName,String password){
        userInfoService.insert(userName,password);
        logInfoService.insert(userName,"用户注册成功");
    }
}

@Service
public class LogInfoService {
    @Autowired
    private LogInfoMapper logInfoMapper;
    @Transactional( propagation = Propagation.REQUIRED)
    public Integer insert(String userName, String op) {
    	Integer i = 10/0;
        return logInfoMapper.insert(userName,op);
    }
}
@Service
public class UserInfoService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Transactional( propagation = Propagation.REQUIRED)
    public Integer insert(String userName, String password) {
        return userInfoMapper.insert(userName,password);
    }
}

运⾏程序,程序报错,发现数据库没有插⼊任何数据
流程描述:

  1. insertInfo⽅法开始事务
  2. ⽤⼾注册, 插⼊⼀条数据 (执⾏成功) (和insertInfo使⽤同⼀个事务)
  3. 记录操作⽇志, 插⼊⼀条数据(出现异常, 执⾏失败) (和insertInfo使⽤同⼀个事务)
  4. 因为步骤3出现异常, 事务回滚. 步骤2和3使⽤同⼀个事务 所以步骤2的数据也回滚了

REQUIRES_NEW

将上述代码中将上述UserService和LogService的传播机制改为 REQUIRES_NEW
运行程序,我们观察程序,可以看到,user_info中已经成功新增了一条数据,但是log_info中却并没有成功
这是因为REQUIRES_NEW的调用方与被调用着的事务是独立的,之间互不影响.

NEVER

将UserService中的事务传播机制改为NEVER
运行程序,程序报错,数据也没有插入成功,这是因为NEVER的调用方不能有事务,否则会报错,并回滚

NESTED

将UserService和LogService中的传播机制改为NESTED
运行程序,发现似乎和REQUIRED一样,但是当我们手动给LogService进行回滚,就会发现,日志表新增失败了,但是用户表注册成功了,也就是说,调用方的事务包含被调用者的事务,但是被调用者的事务也是一个独立的事务,因此可以实现局部回滚

REQUIRED和NESTED的区别

整个事务如果全部执⾏成功, ⼆者的结果是⼀样的
如果事务⼀部分执⾏成功, REQUIRED加⼊事务会导致整个事务全部回滚. NESTED嵌套事务可以实现局部回滚, 不会影响上⼀个⽅法中执⾏的结果

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值