深入理解TransaationTemplate编程式事务

TransactionTemplate的编程式事务管理是使用模板方法设计模式对原始事务管理方式的封装。

一、TransaationTemplate 源码分析

点开源码看后发现他的核心是execute,如下

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
public class TransactionTemplate extends DefaultTransactionDefinition
implements TransactionOperations, InitializingBean {

@Override
@Nullable
public <T> T execute(TransactionCallback<T> action) throws TransactionException {
// 判断事务管理器是否存在
Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
// 如果是transactionManager继承于CallbackPreferringPlatformTransactionManager,则使用如果是transactionManager继承于CallbackPreferringPlatformTransactionManager的execute方法
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
}
else {
// 获取事务状态
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try {
// 执行用户操作
result = action.doInTransaction(status);
}
catch (RuntimeException | Error ex) {
// Transactional code threw application exception -> rollback
// 回滚事务
rollbackOnException(status, ex);
// 抛出异常
throw ex;
}
catch (Throwable ex) {
// Transactional code threw unexpected exception -> rollback
// 回滚事务
rollbackOnException(status, ex);
// 如果异常是未声明的,抛出UndeclaredThrowableException异常。
throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
}
// 提交事务
this.transactionManager.commit(status);
// 返回结果
return result;
}
}

/**
* 执行回滚,正确处理回滚异常
* Perform a rollback, handling rollback exceptions properly.
* @param status object representing the transaction
* @param ex the thrown application exception or error
* @throws TransactionException in case of a rollback error
*/
private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException {
Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");

logger.debug("Initiating transaction rollback on application exception", ex);
try {
this.transactionManager.rollback(status);
}
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
ex2.initApplicationException(ex);
throw ex2;
}
catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by rollback exception", ex);
throw ex2;
}
}


}

在来分析execute的唯一参数 TransactionCallback

查看接口TransactionCallback.java 发现其仅有一个方法:

1
2
3
public interface TransactionCallback<T> {
T doInTransaction(TransactionStatus var1);
}

并且有一个抽象类TransactionCallbackWithoutResult实现了接口TransactionCallback。

1
2
3
4
5
6
7
8
9
10
11
public abstract class TransactionCallbackWithoutResult implements TransactionCallback<Object> {
public TransactionCallbackWithoutResult() {
}

public final Object doInTransaction(TransactionStatus status) {
this.doInTransactionWithoutResult(status);
return null;
}

protected abstract void doInTransactionWithoutResult(TransactionStatus var1);
}

所以当我们借助TransactionTemplate.execute( … )执行事务管理的时候,传入的参数有两种选择:
1、TransactionCallback
2、TransactionCallbackWithoutResult
两种区别从命名看就相当明显了,一个是有返回值,一个是无返回值。这个的选择就取决于你是读还是写了。

二、TransactionStatus 解析

2.1 TransactionStatus接口

TransactionStatus表示一个事物的状态。接口提供了控制事务执行和查询事务状态的方法。比如当前调用栈中之前已经存在了一个事物,那么就是通过该接口来判断的,TransactionStatus接口可以让事务管理器控制事务的执行,比如检查事务是否为一个新事务,或者是否只读,TransactionStatus还可以初始化回滚操作。

接口源码

1
2
3
4
5
6
7
8
9
10
11
// 交易状态的表示。事务代码可以使用它来检索状态信息,并以编程方式请求回滚(而不是抛出导致隐式回滚的异常)。
public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {

// 返回此事务内部是否带有保存点,即是否已创建为基于保存点的嵌套事务。
boolean hasSavepoint();

// 将底层会话刷新到数据存储区(如果适用):例如,所有受影响的 Hibernate/JPA 会话。这实际上只是一个提示,如果底层事务管理器没有刷新概念,则可能是无操作的。根据底层资源,刷新信号可能会应用于主要资源或事务同步。
@Override
void flush();

}

TransactionExecution 接口源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 事务当前状态的通用表示
public interface TransactionExecution {

// 返回当前交易是否是新的;以其他方式参与现有事务,或者可能一开始就没有在实际事务中运行。
boolean isNewTransaction();

// 仅设置事务回滚。这指示事务管理器事务的唯一可能结果可能是回滚,作为抛出异常的替代方案,而异常又会触发回滚。
void setRollbackOnly();

// 返回事务是否已被标记为仅回滚(由应用程序或事务基础结构)。
boolean isRollbackOnly();

// 返回此事务是否完成,即是否已经提交或回滚。
boolean isCompleted();

}

SavepointManager源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 指定 API 以以通用方式以编程方式管理事务保存点的接口。由 TransactionStatus 扩展以公开特定事务的保存点管理功能。
// 请注意,保存点只能在活动事务中工作。只需将此程序化保存点处理用于高级需求;否则,最好使用带有 PROPAGATION_NESTED 的子事务。
public interface SavepointManager {

// 创建一个新的保存点。您可以通过rollbackToSavepoint到特定的保存点,并通过releaseSavepoint显式释放您不再需要的保存点。
// 请注意,大多数事务管理器将在事务完成时自动释放保存点。
// 返回值:一个保存点对象,被传递到rollbackToSavepoint或releaseSavepoint
Object createSavepoint() throws TransactionException;

// 回滚到给定的保存点。保存点之后不会自动释放。您可以显式调用releaseSavepoint(Object)或依赖事务完成时的自动释放。
void rollbackToSavepoint(Object savepoint) throws TransactionException;

// 显式释放给定的保存点。
// 请注意,大多数事务管理器将在事务完成时自动释放保存点。
/如果适当的资源清理最终会在事务完成时发生,那么实现应该尽可能静默地失败。
void releaseSavepoint(Object savepoint) throws TransactionException;

}