前言

  • Spring 事务的管理,是通过 org.springframework.transaction.PlatformTransactionManager 进行管理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// PlatformTransactionManager.java

public interface PlatformTransactionManager {

// 根据事务定义 TransactionDefinition ,获得 TransactionStatus 。
TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;

// 根据情况,提交事务
void commit(TransactionStatus status) throws TransactionException;

// 根据情况,回滚事务
void rollback(TransactionStatus status) throws TransactionException;

}
  • PlatformTransactionManager 是负责事务管理的接口,一共有三个接口方法,分别负责事务的获得、提交、回滚。
    • #getTransaction(TransactionDefinition definition)
      • 根据事务定义 TransactionDefinition ,获得 TransactionStatus
      • 为什么不是创建事务呢?因为如果当前如果已经有事务,则不会进行创建,一般来说会跟当前线程进行绑定。如果不存在事务,则进行创建
      • 什么返回的是 TransactionStatus 对象?在 TransactionStatus 中,不仅仅包含事务属性,还包含事务的其它信息,例如是否只读、是否为新创建的事务等等
    • #commit(TransactionStatus status)
      • 根据 TransactionStatus 情况,提交事务
      • 为什么根据 TransactionStatus 情况,进行提交?例如说,带@Transactional 注解的的 A 方法,会调用 @Transactional 注解的的 B 方法。
        • B 方法结束调用后,会执行 PlatformTransactionManager#commit(TransactionStatus status) 方法,此处事务是不能、也不会提交的。
        • 而是在 A 方法结束调用后,执行 PlatformTransactionManager#commit(TransactionStatus status) 方法,提交事务。
    • #rollback(TransactionStatus status)
      • 根据 TransactionStatus 情况,回滚事务
      • 为什么根据 TransactionStatus 情况,进行回滚?原因同 #commit(TransactionStatus status) 方法。

子类

  • 先来一张PlatformTransactionManager接口的子类图
  • PlatformTransactionManager 有抽象子类 org.springframework.transaction.support.AbstractPlatformTransactionManager ,基于 模板方法模式实现事务整体逻辑的骨架,而抽象 #doCommit(DefaultTransactionStatus status)、#doRollback(DefaultTransactionStatus status) 等等方法,交由子类类来实现。

  • 不同的数据持久层框架,会有其对应的 PlatformTransactionManager 实现类

    • HibernateTransactionManager
      • Hibernate5 的事务管理做集成
    • DataSourceTransactionManager
      • JDBC 的事务管理做集成。所以,它也适用于 MyBatis、Spring JDBC 等等。
      • 最常使用的
    • JpaTransactionManager
      • JPA 的事务管理做集成

其他支持类

TransactionDefinition
  • @Transactional 注解的属性,会解析成 org.springframework.transaction.TransactionDefinition 对象,即事务定义
1
2
3
4
5
6
7
8
9
10
public interface TransactionDefinition {

int getPropagationBehavior(); // 事务的传播行为
int getIsolationLevel(); // 事务的隔离级别
int getTimeout(); // 事务的超时时间
boolean isReadOnly(); // 事务是否只读
@Nullable
String getName(); // 事务的名字

}
  • TransactionDefinition继承关系图
  • @Transactional 注解的 rollbackFor、rollbackForClassName、noRollbackFor、noRollbackForClassName 属性貌似没体现出来?它们提现在 TransactionDefinition 的实现类 RuleBasedTransactionAttribute中。
TransactionStatus
  • TransactionStatus 接口,记录事务的状态,不仅仅包含事务本身,还包含事务的其它信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// TransactionStatus.java

public interface TransactionStatus extends SavepointManager, Flushable {

/**
* 是否是新创建的事务
*/
boolean isNewTransaction();

/**
* 是否有 Savepoint
*
* 在 {@link TransactionDefinition#PROPAGATION_NESTED} 传播级别使用。
*/
boolean hasSavepoint();

/**
* 设置为只回滚
*/
void setRollbackOnly();
/**
* 是否为只回滚
*/
boolean isRollbackOnly();

/**
* 执行 flush 操作
*/
@Override
void flush();

/**
* 是否事务已经完成
*/
boolean isCompleted();

}
  • TransactionStatus继承关系图
  • 为什么没有事务对象呢?在 TransactionStatus 的实现类 DefaultTransactionStatus 中,有个 Object transaction 属性,表示事务对象。
  • #isNewTransaction() 方法,表示是否是新创建的事务。有什么用呢?
    • 我们对 #commit(TransactionStatus status) 方法的解释。通过该方法,我们可以判断,当前事务是否当前方法所创建的,只有创建事务的方法,才能且应该真正的提交事务。
  • 子类
    • org.springframework.transaction.interceptor.TransactionAttribute
      • 支持定义返回异常回滚的事务定义接口
    • org.springframework.transaction.interceptor.RuleBasedTransactionAttribute
      • 基于 {@link RollbackRuleAttribute} 的事务定义实现类
      • 每个 @Transactional 注解的方法及每个<tx:method />``XML的配置 都会被解析成此对象

总结

  • 使用 Spring 事务有什么优点?
    • 通过 PlatformTransactionManager ,为不同的数据层持久框架提供统一的 API ,无需关心到底是原生 JDBC、Spring JDBC、JPA、Hibernate 还是 MyBatis

参考