一、配置方式
spring支持编程式事务管理以及声明式事务管理两种方式。
-
编程式事务:是侵入性事务管理,使用TransactionTemplate或者直接使用PlatformTransactionManager,对于编程式事务管理,spring推荐使用TransactionTemplate。
-
声明式事务:建立在AOP之上,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,执行完目标方法之后根据执行的情况提交或者回滚,声明式事务最大的优点就是不需要通过编程的方式管理事务(即不需要侵入代码)。
-
两种方式比较:
显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的编程方式。和编程式事务管理相比,唯一不足的地方就是声明式事务管理的粒度是到方法级别
,而编程式事务管理是可以到代码块的,但是可以通过提取方法
的方式完成声明式事务管理的配置。
二、隔离级别(isolation)
Spring默认为DEFAULT,用法:
// Spring默认为DEFAULT
@Transactional(isolation = Isolation.DEFAULT)
- DEFAULT:默认的隔离级别,使用数据库默认的事务隔离级别。
- READ_UNCOMMITTED:这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。
会产生脏读,不可重复读和幻读。 - READ_COMMITTED:保证一个事务修改的数据提交后才能被另外一个事务读取,其它事务不能读取该事务未提交的数据。
避免脏读出现,但是可能会出现不可重复读和幻读。 - REPEATABLE_READ:保证一个事务不能读取另一个事务未提交的数据,避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。
防止脏读,不可重复读,但是可能出现幻读。 - SERIALIZABLE:这是最可靠的但是代价花费最高的事务隔离级别,事务被处理为顺序执行。
避免了脏读、不可重复读、幻读。
question:如果数据库事务跟spring事务的隔离级别不一样会如何?
三、传播机制(propagation)
事务的传播性一般用在事务嵌套的场景,比如事务A里面调用了另外一个事务方法,那么两个方法是各自作为独立的方法提交还是内层的事务合并到外层的事务一起提交,这就是需要事务传播机制的配置来确定怎么样执行。
Spring默认为REQUIRED,用法:
// Spring默认为REQUIRED
@Transactional(propagation = Propagation.REQUIRED)
7种事务的传播机制:
- REQUIRED(需要):(Spring默认)支持使用当前事务,如果当前事务不存在,创建一个新事务。
- SUPPORTS(支持):支持使用当前事务,如果当前事务不存在,则不使用事务。
- MANDATORY(强制):支持使用当前事务,如果当前事务不存在,则抛出Exception。
- REQUIRES_NEW(需要新建):创建一个新事务,如果当前事务存在,把当前事务挂起。
- NOT_SUPPORTED(不支持):不支持事务执行,如果当前事务存在,把当前事务挂起。
- NEVER(决不):不支持事务执行,如果当前有事务则抛出Exception。
- NESTED(嵌套):嵌套事务,如果当前事务存在,那么在嵌套的事务中执行。如果当前事务不存在,则表现跟REQUIRED一样。