写在前面
基于Spring事务,官方推荐使用@Transactional注解的声明式事务,使用便捷,无需关心底层实现,只需关心注解中的参数含义及使用规则。
然而在很多场景下(特别是复杂的业务逻辑、更甚在子线程、多线程中),往往声明式事务会出现意想不到的结果。这时候针对特定场景,这时编程式事务更加得心应手。
代码实现
以下是一个简版的小工具,没有太复杂的场景基本可以满足
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;
/**
* Spring 编程时事务帮助类
* <p>
* 执行时可根据需求设置传播行为或隔离级别TransactionDefinition
* 传播行为:{@link TransactionTemplate#setPropagationBehavior(int)} 参数来自默认:{@link TransactionDefinition#PROPAGATION_REQUIRED}
* 隔离级别(慎重,除特殊情况外,推荐保持默认):{@link TransactionTemplate#setIsolationLevel(int)} (int)} 参数来自默认:{@link TransactionDefinition#ISOLATION_DEFAULT}
*
*/
@Component
public class TransactionHelper {
private final TransactionTemplate transactionTemplate;
/**
* 存储初始化 TransactionTemplate 时的传播机制和隔离级别
*/
private final static int[] INITIALIZE_TRANSACTION_TEMPLATE_PROPS = new int[2];
public TransactionHelper(@Nullable PlatformTransactionManager platformTransactionManager) {
this.transactionTemplate = new TransactionTemplate(platformTransactionManager);
INITIALIZE_TRANSACTION_TEMPLATE_PROPS[0] = this.transactionTemplate.getPropagationBehavior();
INITIALIZE_TRANSACTION_TEMPLATE_PROPS[1] = this.transactionTemplate.getIsolationLevel();
}
/**
* 执行带返回的事务回调
*
* @param callback - 不带返回值回调
*/
public static void executeWithoutResult(@NonNull ICallFunc callback) {
executeWithoutResult(callback, TransactionDefinition.PROPAGATION_REQUIRED);
}
/**
* 执行带返回的事务回调
*
* @param callback - 不带返回值回调
* @param propagationBehavior - 事务传播行为(通过{@link TransactionDefinition}获取)
*/
public static void executeWithoutResult(@NonNull ICallFunc callback, int propagationBehavior) {
executeWithoutResult(callback, propagationBehavior, TransactionDefinition.ISOLATION_DEFAULT);
}
/**
* 执行带返回的事务回调
*
* @param call - 不带返回值回调
* @param propagationBehavior - 事务传播行为(通过{@link TransactionDefinition}获取)
* @param isolationLevel - 事务隔离级别(通过{@link TransactionDefinition}获取)
*/
public static void executeWithoutResult(@NonNull ICallFunc call, int propagationBehavior, int isolationLevel) {
final TransactionTemplate template = getInstance().getTransactionTemplate();
try {
template.setPropagationBehavior(propagationBehavior);
template.setIsolationLevel(isolationLevel);
template.executeWithoutResult(status -> call.call());
} finally {
if (!(INITIALIZE_TRANSACTION_TEMPLATE_PROPS[0] == template.getPropagationBehavior()
&& INITIALIZE_TRANSACTION_TEMPLATE_PROPS[1] == template.getIsolationLevel())) {
synchronized (INITIALIZE_TRANSACTION_TEMPLATE_PROPS) {
template.setPropagationBehavior(INITIALIZE_TRANSACTION_TEMPLATE_PROPS[0]);
template.setIsolationLevel(INITIALIZE_TRANSACTION_TEMPLATE_PROPS[1]);
}
}
}
}
/**
* 执行带返回的事务回调
*
* @param callback - 带返回值回调
* @param <T> - 返回类型
*/
public static <T> T execute(@NonNull ICallBackFunc<T> callback) {
return execute(callback, TransactionDefinition.PROPAGATION_REQUIRED);
}
/**
* 执行带返回的事务回调
*
* @param callback - 带返回值回调
* @param propagationBehavior - 事务传播行为(通过{@link TransactionDefinition}获取)
* @param <T> - 返回类型
*/
public static <T> T execute(@NonNull ICallBackFunc<T> callback, int propagationBehavior) {
return execute(callback, propagationBehavior, TransactionDefinition.ISOLATION_DEFAULT);
}
/**
* 执行带返回的事务回调
*
* @param callback - 带返回值回调
* @param propagationBehavior - 事务传播行为(通过{@link TransactionDefinition}获取)
* @param isolationLevel - 事务隔离级别(通过{@link TransactionDefinition}获取)
* @param <T> - 返回类型
*/
public static <T> T execute(@NonNull ICallBackFunc<T> callback, int propagationBehavior, int isolationLevel) {
TransactionTemplate template = getInstance().getTransactionTemplate();
try {
template.setPropagationBehavior(propagationBehavior);
template.setIsolationLevel(isolationLevel);
return template.execute(status -> callback.call());
} finally {
if (!(INITIALIZE_TRANSACTION_TEMPLATE_PROPS[0] == template.getPropagationBehavior()
&& INITIALIZE_TRANSACTION_TEMPLATE_PROPS[1] == template.getIsolationLevel())) {
synchronized (INITIALIZE_TRANSACTION_TEMPLATE_PROPS) {
template.setPropagationBehavior(INITIALIZE_TRANSACTION_TEMPLATE_PROPS[0]);
template.setIsolationLevel(INITIALIZE_TRANSACTION_TEMPLATE_PROPS[1]);
}
}
}
}
protected static TransactionHelper getInstance() {
return SpringUtil.getBean(TransactionHelper.class);
}
protected TransactionTemplate getTransactionTemplate() {
return this.transactionTemplate;
}
@FunctionalInterface
public interface ICallFunc {
void call();
}
@FunctionalInterface
public interface ICallBackFunc<R> {
R call();
}
}