Spring事务的种类、隔离级别、传播方式
事务种类
Spring为事务管理提供了一致的编程模板,在高层次上建立了统一的事务抽象。也就是说,不管是选择MyBatis、Hibernate、JPA还是Spring JDBC,Spring都可以让用户以统一的编程模型进行事务管理。
Spring支持两种事务编程模型:
-
编程式事务
Spring提供了
TransactionTemplate
模板,利用该模板我们可以通过编程的方式实现事务管理,而无需关注资源获取、复用、释放、事务同步及异常处理等操作。相对于声明式事务来说,这种方式相对麻烦一些,但是好在更为灵活,我们可以将事务管理的范围控制的更为精确。 -
声明式事务
Spring事务管理的亮点在于声明式事务管理,它允许我们通过声明的方式,在IoC配置中指定事务的边界和事务属性,Spring会自动在指定的事务边界上应用事务属性。声明式事务最大的优点就是不需要在业务逻辑代码中掺杂事务管理的代码, 只需在配置文件中做相关的事务规则声明或通过
@Transactional
注解的方式,便可以将事务规则应用到业务逻辑中。声明式事务管理要优于编程式事务管理,这正是 spring 倡导的非侵入式的开发方式,使业务代码不受污染,只要加上注解就可以获得完全的事务支持。唯一不足地方是,最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。
事务的隔离级别
Spring的事务是基于数据库事务的基础上,如果数据库没有事务机制,那么Spring也就没有事务;
public enum Isolation {
DEFAULT(-1),
READ_UNCOMMITTED(1),
READ_COMMITTED(2),
REPEATABLE_READ(4),
SERIALIZABLE(8);
private final int value;
private Isolation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
定义了五个表示隔离级别的常量:
(1) TransactionDefinition.ISOLATION_DEFAULT
: 使⽤后端数据库默认的隔离级别, Mysql 默认采⽤的 REPEATABLE_READ 隔离级别;Oracle 默认采⽤的READ_COMMITTED 隔离级别.
(2) TransactionDefinition.ISOLATION_READ_UNCOMMITTED
: 最低的隔离级别,允许读取尚未提交的数据变更, 可能会导致脏读、幻读或不可重复读
(3) TransactionDefinition.ISOLATION_READ_COMMITTED
: 允许读取并发事务已经提交的数据, 可以阻止脏读,但是幻读或不可重复读仍有可能发生
(4) TransactionDefinition.ISOLATION_REPEATABLE_READ
: 对同⼀字段的多次读取结果都是⼀致的,除非数据是被本身事务自己所修改, 可以阻止脏读和不可重复读,但幻读仍有可能发⽣。
(5) TransactionDefinition.ISOLATION_SERIALIZABLE
: 最⾼的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会⽤到该级别。
事务的传播方式
Spring在TransactionDefinition接口中规定了7种类型的事务传播行为,它们规定了事务方法和事务方法发生嵌套调用时如何进行传播:
int PROPAGATION_REQUIRED = 0;
int PROPAGATION_SUPPORTS = 1;
int PROPAGATION_MANDATORY = 2;
int PROPAGATION_REQUIRES_NEW = 3;
int PROPAGATION_NOT_SUPPORTED = 4;
int PROPAGATION_NEVER = 5;
int PROPAGATION_NESTED = 6;
支持当前事务的情况:
(1)TransactionDefinition.PROPAGATION_REQUIRED
: 如果当前存在事务, 则加入该事务;如果当前没有事务,则创建⼀个新的事务。使用的最多的一个事务传播行为,我们平时经常使用的@Transactional
注解默认使用就是这个事务传播行为。
(2) TransactionDefinition.PROPAGATION_SUPPORTS
: 如果当前存在事务,则加⼊该事务;如果当前没有事务,则以非事务的方式运行。
(3) TransactionDefinition.PROPAGATION_MANDATORY
: 如果当前存在事务,则加⼊该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)
不支持当前事务的情况:
(1)TransactionDefinition.PROPAGATION_REQUIRES_NEW
: 创建⼀个新的事务,如果当前存在事务,则把当前事务挂起。
(2)TransactionDefinition.PROPAGATION_NOT_SUPPORTED
: 以非事务的方式运行,如果当前存在事务,则把当前事务挂起。
(3)TransactionDefinition.PROPAGATION_NEVER
: 以非事务的方式运行,如果当前存在事务,则抛出异常。
其他情况:
(1)TransactionDefinition.PROPAGATION_NESTED
: 如果当前存在事务,则创建⼀个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED
。