Spring编程式事务管理详解
目录
- 事务管理器核心接口
- 事务定义配置
- 事务状态控制
- 编程式事务实现
- 手动事务管理
- 事务模板应用
事务管理器核心接口
PlatformTransactionManager是Spring框架处理事务的核心接口,它为不同的事务管理实现提供了一个统一的编程模型。Spring本身并不直接管理事务,而是通过这个接口来适配各种底层的事务机制。该接口主要包含三个核心方法:
public interface PlatformTransactionManager {
// 根据事务定义获取或创建事务
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
// 提交当前事务
void commit(TransactionStatus status) throws TransactionException;
// 回滚当前事务
void rollback(TransactionStatus status) throws TransactionException;
}
核心方法说明:
- getTransaction(TransactionDefinition definition)
- 根据事务定义(传播行为、隔离级别、超时等)获取一个事务
- 如果当前线程已有事务,根据传播行为决定是加入还是新建
- 返回TransactionStatus对象,表示当前事务状态
- commit(TransactionStatus status)
- 提交事务
- 如果事务已标记为rollback-only,则执行回滚
- rollback(TransactionStatus status)
- 回滚事务
事务定义配置
TransactionDefinition接口用于定义事务的属性,描述事务的边界和行为规则。主要包括以下几个方面:
- 传播行为(Propagation)
- REQUIRED(默认):如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务
- REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起
- NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务;如果当前没有事务,则等价于REQUIRED
- SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行
- NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起
- NEVER:以非事务方式运行,如果当前存在事务,则抛出异常
- MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常
- 隔离级别(Isolation)
- DEFAULT:使用底层数据库的默认隔离级别
- READ_UNCOMMITTED:读未提交
- READ_COMMITTED:读已提交
- REPEATABLE_READ:可重复读
- SERIALIZABLE:串行化
- 超时时间(Timeout)
- 是否只读(Read-only)
事务状态控制
TransactionStatus接口表示事务的状态,用于在事务的执行过程中查询状态和控制事务:
public interface TransactionStatus extends SavepointManager {
// 判断是否是新的事务
boolean isNewTransaction();
// 判断是否有保存点
boolean hasSavepoint();
// 设置事务为只回滚
void setRollbackOnly();
// 判断事务是否已被标记为只回滚
boolean isRollbackOnly();
// 判断事务是否已完成
boolean isCompleted();
}
编程式事务实现
编程式事务允许开发人员在代码中显式调用事务管理API来控制事务边界,提供了比声明式事务更细粒度的事务控制能力。
手动事务管理
首先,在Spring配置文件中配置一个事务管理器:
<bean class="org.springframework.transaction.support.TransactionTemplate" id="transactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
然后在服务层注入事务管理器,并编写相应的方法。以下示例使用MyBatis作为ORM框架:
public class AccountService {
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private AccountRepository accountRepository;
public void transferAccounts() {
// 1. 定义默认的事务属性
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
// 2. 获取事务状态
TransactionStatus transaction = transactionManager.getTransaction(definition);
try {
// 执行数据库操作
accountRepository.updateAccountBalance(1, 100.0);
accountRepository.updateAccountBalance(2, -100.0);
// 提交事务
transactionManager.commit(transaction);
} catch (Exception e) {
// 发生异常时回滚事务
transactionManager.rollback(transaction);
throw new RuntimeException("账户转账失败", e);
}
}
}
运行此方法后,你会发现数据修改成功,看起来似乎是否添加事务没有区别。接下来,在代码中抛出一个异常:
即使已经调用了接口方法,数据也没有被修改,这表明事务被成功回滚了!
事务模板应用
Spring提供了TransactionTemplate类,它封装了事务管理的复杂性,使编程式事务更加简洁:
首先,在Spring配置文件中配置事务模板:
<bean class="org.springframework.transaction.support.TransactionTemplate" id="transactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
然后注入TransactionTemplate到服务类:
public class OrderService {
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private OrderRepository orderRepository;
/**
* 使用TransactionTemplate执行事务操作
* TransactionTemplate是Spring提供的事务模板类,简化了编程式事务的代码
*/
public void processOrder() {
// 调用TransactionTemplate的execute方法,传入事务回调接口
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
// 重写回调接口的doInTransactionWithoutResult方法
// 该方法内的代码会在事务环境中执行
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
// 创建订单
orderRepository.createOrder(new Order("ORD123", 99.99));
// 模拟异常情况
if (true) {
throw new RuntimeException("模拟系统异常");
}
// 更新库存
orderRepository.updateInventory("PROD456", -1);
} catch (Exception e) {
// 异常处理:标记事务为需要回滚
status.setRollbackOnly();
}
}
});
}
}
可以通过transactionTemplate.setIsolationLevel()方法设置事务的隔离级别,从而满足不同业务场景的需求。