前言
众所周知,Spring是实现事务配置是通过注解 Transactional 来实现的,但是注解中含有多个参数, 其中rollbackFor、propagation、isolation,这个三个参数算是比较常用的,本文主要讲解一下以上参数:
异常捕获rollbackFor:
- 关于异常的介绍,推荐博文: https://blog.csdn.net/zhangerqing/article/details/8248186
- Spring框架的事务管理默认地只在发生不受控异常(RunTimeException 以及其子类)时会进行事务回滚,但是当方法运行时抛出受控异常(非RunTimeException 以及其子类)时 transactionManager并不会回滚,
- rollbackFor 用于捕获相应异常,并且进行事务回滚,默认是RunTimeException ,但是Alibaba 开发手册中提醒我们指定 所要捕获的异常类型,用于事务控制,例如捕获所有异常配置:
// 所有异常都会回滚
@Transactional(rollbackFor = Exception.class)
事务传播机制propagation:
- Spring的传播机制有7种:
类型 | 参数名 | 解释 |
---|---|---|
支持当前事务 | Propagation. REQUIRED(默认) | 如果当前没有事务,就新建一个事务,如果有事务,就加入其中 |
支持当前事务 | Propagation.SUPPORTS | 支持当前事务,如果没有事务,则以非事务的形式执行 |
支持当前事务 | Propagation.MANDATORY | 支持当前事务,如果没有事务,就抛出异常 |
不支持当前事务 | Propagation.REQUIRES_NEW | 新建事务,如果存在事务,就将事务挂起,新建一个事务 |
不支持当前事务 | Propagation.NOT_SUPPORTED | 以非事务的方式执行,当前存在事务,就把当前事务挂起 |
不支持当前事务 | Propagation.NEVER | 以非事务的方式执行,如果当前有事务,则抛出异常 |
事务嵌套 | Propagation.NESTED | 如果当前存在事务,则在嵌套事务中执行;如果当前没有事务,则执行与Propagation. REQUIRED类似的操作 |
-
其中常用的事务传播机制有:
Propagation. REQUIRED:默认
Propagation.NOT_SUPPORTED:用于新业务不影响主体业务逻辑,及时业务执行异常也不会影响主体业务逻辑
Propagation.REQUIRES_NEW:一般用于记录业务日志 -
Propagation.NESTED 是较为难理解的事务隔离: 当前存在事务时,会发生嵌套事务,会在子方法执行前,加入SavePoint, 当子事务回滚时,会回到当前点,主体逻辑不会回滚,只有当主业务提交之后,才会全部提交。
-
注意Spring 事务控制是根据捕获异常信息来处理的,如在业务中捕获了异常会造成事务回滚失败;但是Spring捕获异常后不会处理异常,会继续向上抛出,开启多个事务时,也需要try-catch 的使用,避免异常上抛,导致其他事务回滚,逻辑执行异常。
// 所有异常都会回滚,事务:Propagation. REQUIRED
@Transactional(rollbackFor = Exception.class)
public void addUser(){
......
}
// 所有异常都会回滚,事务:Propagation. REQUIRES_NEW
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
public void addOrder(){
......
}
隔离级别:isolation
- 推荐一下自己的博客Mysql事务隔离机制: https://blog.csdn.net/zhangyong01245/article/details/93888868
- 其实Spring的隔离级别,就是对应数据库隔离级别的一种实现
- Spring的事务隔离级别,共有5中:
参数值 | 名称 | 解释 |
---|---|---|
Isolation. DEFAULT | Default | 默认的事务隔离级别,默认是用数据库的事务隔离级别 |
Isolation. READ_UNCOMMITTED | 未提交读 | 脏读,不可重复读、幻读都存在 |
Isolation. READ_COMMITTED | 已提交读 | 避免脏读,但是存在不可重复读,幻读 |
Isolation. REPEATABLE_READ | 可重复读 | 避免脏读和不可重复读,但是有幻读的可能 |
Isolation. SERIALIZABLE | 串行话 | 避免以上所有读的问题 |
- 示例
// 所有异常都会回滚,事务隔离机制已提交读
@Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)