面试经常问到关于Spring事务的问题,包括怎么开启,开启原理等。现整理总结如下。
目录
2.2 PlatformTransactionManager
1、Spring事务简介
参考之前写的文章:Spring事务整理篇
2、Spring开启事务的主要接口介绍
Spring事务抽象一共有3个主要接口,他们都在
org.springframework.transaction
包下。
TransactionDefinition:
负责定义事务相关属性,包括隔离级别、传播行为等。PlatformTransactionManager:
是Spring事务框架的核心接口,它为应用程序提供事务边界的统一方式,它根据TransactionDefinition
的定义来开启相关事务。TransactionStatus:
事务开启期间的事务状态由TransactionStatus
负责,也可以通过TransactionStatus
对事务进行有限的控制。
下面分别分析这三个接口。
2.1 TransactionDefinition
负责定义事务相关属性,包括隔离级别、传播行为等。
详细参考文章: Spring五大隔离级别与事务传播属性
1)Spring五大隔离级别
- 默认 DEFAULT
这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应。
- 读未提交 READ_UNCOMMITTED
这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读(读的时候可以更改)和幻像读(读的时候可以插入)。
- 读已提交 READ_COMMITTED
保证一个事务修改的数据提交后才能被另外一个事务读取,另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读(读的时候可以更改)和幻像读(读的时候可以插入)。
- 可重复 REPEATABLE_READ
这种事务隔离级别可以防止脏读、不可重复读,但是可能出现幻像读(读的时候可以插入)。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读。
- 串行化 SERIALIZABLE
这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。除了防止脏读、不可重复读外,还避免了幻像读。
2)Spring事务传播行为
/*
默认的事务传播行为,如果存在当前事务,则加入,如果不存在事务,则创建一个新事务。
*/
int PROPAGATION_REQUIRED = 0;
/*
如果当前存在一个事务,则加入当前事务,如果不存在,则直接执行。
对于一些查询方法来说,PROPAGATION_SUPPORTS比较适合,如果当前方法被其他方法调用,而其他方法启动了一个事务,此行为可以保证当前方法加入当前事务,并洞察当前事务对数据资源所做的更新。其他传播方式则看不到更新,因为当前事务没有提交。
*/
int PROPAGATION_SUPPORTS = 1;
/*
PROPAGATION_MANDATORY强制要求当前存在一个事务,如果不存在,则抛出异常。
*/
int PROPAGATION_MANDATORY = 2;
/*
不管当前是否存在事务, 都会创建一个新的事务。如果当前存在事务,会将当前事务挂起。如果某个业务对象不想影响外层事务,可以选择PROPAGATION_REQUIRES_NEW。
*/
int PROPAGATION_REQUIRES_NEW = 3;
/*
不支持当前事务,而是在没有事务的情况下执行。如果当前存在事务,则将当前事务挂起,但要看PlatformTransactionManager的实现类是否支持事务的挂起。
*/
int PROPAGATION_NOT_SUPPORTED = 4;
/*
永远不支持事务,如果存在事务,则抛出异常。
*/
int PROPAGATION_NEVER = 5;
/*
如果存在事务,则在当前事务的一个嵌套事务中执行。与PROPAGATION_REQUIRES_NEW类似,但与PROPAGATION_REQUIRES_NEW创建的事务与原有事务为同一档次,在新事务运行时原有事务被挂起;PROPAGATION_NESTED创建的事务寄生在外层事务,地位比外层事务低,嵌套事务执行时外层事务也处于活跃状态。
*/
int PROPAGATION_NESTED = 6;
2.2 PlatformTransactionManager
总述:是Spring事务框架的核心接口,它为应用程序提供事务边界的统一方式,它根据TransactionDefinition
的定义来开启相关事务。
Spring并不直接管理事务,而是提供了多种事务管理器 ,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。
Spring事务管理器的接口是: org.springframework.transaction.PlatformTransactionManager ,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。
PlatformTransactionManager接口代码如下:
PlatformTransactionManager接口中定义了三个方法:
Public interface PlatformTransactionManager()...{
// Return a currently active transaction or create a new one, according to the specified propagation behavior(根据指定的传播行为,返回当前活动的事务或创建一个新事务。)
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
// Commit the given transaction, with regard to its status(使用事务目前的状态提交事务)
Void commit(TransactionStatus status) throws TransactionException;
// Perform a rollback of the given transaction(对执行的事务进行回滚)
Void rollback(TransactionStatus status) throws TransactionException;
}
我们刚刚也说了Spring中PlatformTransactionManager根据不同持久层框架所对应的接口实现类,几个比较常见的如下图所示
比如我们在使用JDBC或者iBatis(就是Mybatis)进行数据持久化操作时,我们的xml配置通常如下:
<!-- 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
2.3 TransactionStatus
TransactionStatus接口用来记录事务的状态 该接口定义了一组方法,用来获取或判断事务的相应状态信息。
PlatformTransactionManager.getTransaction(…) 方法返回一个 TransactionStatus 对象。返回的TransactionStatus 对象可能代表一个新的或已经存在的事务(如果在当前调用堆栈有一个符合条件的事务)。
TransactionStatus接口内容如下:
public interface TransactionStatus{
boolean isNewTransaction(); // 是否是新的事务
boolean hasSavepoint(); // 是否有恢复点
void setRollbackOnly(); // 设置为只回滚
boolean isRollbackOnly(); // 是否为只回滚
boolean isCompleted; // 是否已完成
}
3、实例,代码实现开启事务
1)参考:Spring 事务用法示例与实现原理
首先通过一个简单的例子讲解了Spring事务是如何使用的,然后讲解了Spring事务进行标签解析的时候做了哪些工作,最后讲解了Spring事务是如何与Spring Aop进行一一对应的,并且是如何通过Spring Aop实现将事务逻辑织入目标bean的。
- 1. 使用示例
- 2. 标签解析
- 3. 实现原理
- 4. 小结
2)参考:https://www.jianshu.com/p/00b46f2f397c
包含常见的JDBC、Hibernate数据访问方式。