事务
事务是一组操作的集合, 是一个不可分割的整体
事务会把所有的操作作为一个整体, 一起向数据库提交或是撤销操作请求. 所以这组操作要么同时成功, 要么同时失败
Spring 中事务的实现
- 编程式 (手动写代码操作事务)
- 声明式 (通过注解自动开启和提交事务)
编程式事务
- 开启事务 / 获取事务, 通过两个 Spring 内置对象获取
DataSourceTransactionManager
事务管理器, 用来获取, 提交或回滚事务
TransactionDefinition
定义事务的属性, 事务隔离级别, 事务传播机制, 回滚规则 …
- 提交事务
- 回滚事务
Spring 通过 DataSourceTransactionManager (事务管理器) 和 TransactionDefinition (事务的属性) 来获取事务
@Controller public class BasicController { // 获取事务管理器 @Autowired private DataSourceTransactionManager dataSourceTransactionManager; // 定义事务的属性 @Autowired private TransactionDefinition transactionDefinition; @RequestMapping("/registry") public String registry() { // 获取事务 / 开启事务 (transactionStatus 为事务的一个状态, 可以理解为数据库的一个快照) TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); // 业务逻辑 User user = new User(); user.setAge(18); user.setName("zrj"); //提交事务 dataSourceTransactionManager.commit(transactionStatus); //回滚事务 // dataSourceTransactionManager.rollback(transactionStatus); return "ok"; } }
声明式事务
使用注解
@Transactional
既是类注解, 也是方法注解
会对注解范围内所有的 public 修饰的方法 生效
@Transactional :
如果方法执行过程中, 出现异常, 且未被捕获, 就进行事务回滚.
如果异常被程序捕获, 则方法对异常无感知, 认为本次执行成功, 就会进行事务提交. 若异常被捕获仍想回滚:
- 将捕获的异常再次抛出
- 手动回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
@RestController public class PathVariableController { @Transactional() @RequestMapping("/registry") public String registry() { User user = new User(); user.setAge(18); user.setName("zrj"); return "ok"; } }
@Transactional 注解的常用属性
- rollbackFor : 异常回滚属性. 执行能够触发事务回滚的异常类型, 默认只有 运行时异常和 error 才会触发事务回滚, 其他类型异常并不会触发回滚操作
- Isolation : 事务的隔离级别. 默认为 Isolation.DEFAULT
- propergation : 事务的传播机制, 默认值为 Propergation.REQUIRED
事务的隔离级别解决 多个事务同时调用一个数据库的问题
事务的传播机制解决 一个事务在多个节点(方法)中传播的问题
Spring 事务的传播机制 – 7种
Propergation.REQUIRED : 如果当前存在事务, 则加入该事务, 如果当前不存在事务, 则创建一个事务
Propergation.SUPPORTS : 如果当前存在事务, 就加入该事务, 如果当前不存在事务,就以非事务的方式继续执行
Propergation.MANDATORY : 强制性, 如果当前存在事务, 就加入该事务, 如果当前不存在事务, 就报错
Propergation.REQUIED_NEW : 创建一个新事务, 如果当前存在事务, 就将当前事务挂起
Propergation.NOT_SUPPORTED : 以非事务的方式运行, 如果当前存在事务, 就将当前事务挂起
Propergation.NEVER : 以非事务的方式运行, 如果当前存在事务, 就抛出异常
Propergation.NESTED : 如果当前存在事务, 则创建一个事务作为当前事务的嵌套事务/子事务来运行, 如果没有事务, 则创建一个事务
NESTED & REQUIRED
- 如果事务全部执行成功, 二者的结果是一样的
- 如果事务部分执行成功, 部分执行失败, REQUIRED 加入事务 会导致整个事务 全部回滚, NESTED 嵌套事务 可以实现 部分回滚 (savepoint 机制)