前言
事务对于 java web 应用来说,也是比较大的一方面。面试的时候也会经常的问到,包含的内容有:
- 事务的四大特性
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔离性(Isolation)
- 持久性(Durability)
- 事务的隔离级别
- DEFAULT 这是一个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级
- 未提交读(read uncommited) : 脏读,不可重复读,虚读都有可能发生
- 已提交读 (read commited): 避免脏读。但是不可重复读和虚读有可能发生
- 可重复读 (repeatable read) : 避免脏读和不可重复读。但是虚读有可能发生.
- 串行化的 (serializable) : 避免以上所有读问题
-
预期读者
对事务有一定基础的同学,想弄清楚 spring 事务的传播机制
为什么会有传播机制
spring 对事务的控制,是使用 aop 切面实现的,我们不用关心事务的开始,提交 ,回滚,只需要在方法上加 @Transactional 注解,这时候就有问题了。
场景一: serviceA 方法调用了 serviceB 方法,但两个方法都有事务,这个时候如果 serviceB 方法异常,是让 serviceB 方法提交,还是两个一起回滚。
- 场景二:serviceA 方法调用了 serviceB 方法,但是只有 serviceA 方法加了事务,是否把 serviceB 也加入 serviceA 的事务,如果 serviceB 异常,是否回滚 serviceA 。
场景三:serviceA 方法调用了 serviceB 方法,两者都有事务,serviceB 已经正常执行完,但 serviceA 异常,是否需要回滚 serviceB 的数据。
传播机制生效条件
因为 spring 是使用 aop 来代理事务控制 ,是针对于接口或类的,所以在同一个 service 类中两个方法的调用,传播机制是不生效的
传播机制类型
下面的类型都是针对于被调用方法来说的,理解起来要想象成两个 service 方法的调用才可以。
PROPAGATION_REQUIRED (默认)
支持当前事务,如果当前没有事务,则新建事务
-
REQUIRES_NEW
新建事务,如果当前存在事务,则把当前事务挂起
这个方法会独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交
NESTED
如果当前存在事务,它将会成为父级事务的一个子事务,方法结束后并没有提交,只有等父事务结束才提交
- 如果当前没有事务,则新建事务
- 如果它异常,父级可以捕获它的异常而不进行回滚,正常提交
但如果父级异常,它必然回滚,这就是和 REQUIRES_NEW 的区别
SUPPORTS
如果当前存在事务,则加入事务
-
NOT_SUPPORTED
以非事务方式运行
-
MANDATORY
如果当前存在事务,则运行在当前事务中
-
NEVER
以非事务方式运行,如果当前存在事务,则抛出异常,即父级方法必须无事务
一点小说明
一般用得比较多的是 PROPAGATION_REQUIRED , REQUIRES_NEW;
REQUIRES_NEW 一般用在子方法需要单独事务,暂时找不到例子,以后补充 。完整的演示程序