Spring事务管理机制
约 1538 字大约 5 分钟
springtransaction
2025-03-23
概述
Spring 事务管理是企业级应用开发中最核心的基础设施之一。它提供了声明式和编程式两种事务管理方式,通过统一的抽象层 PlatformTransactionManager 屏蔽底层事务 API 的差异,使得开发者可以用一致的方式管理 JDBC、JPA、Hibernate 等不同数据访问技术的事务。
事务管理架构
@Transactional 注解
@Transactional 是 Spring 声明式事务的核心注解,可以标注在类或方法上:
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private InventoryService inventoryService;
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.READ_COMMITTED,
timeout = 30,
readOnly = false,
rollbackFor = BusinessException.class,
noRollbackFor = NotificationException.class
)
public Order createOrder(OrderRequest request) {
Order order = new Order(request);
orderRepository.save(order);
inventoryService.reduceStock(request.getProductId(), request.getQuantity());
return order;
}
@Transactional(readOnly = true)
public List<Order> queryOrders(String userId) {
return orderRepository.findByUserId(userId);
}
}事务传播级别
事务传播行为定义了当一个事务方法被另一个事务方法调用时,事务应该如何传播。
| 传播级别 | 行为 | 使用场景 |
|---|---|---|
REQUIRED | 当前有事务则加入,没有则新建 | 默认值,大多数业务方法 |
REQUIRES_NEW | 总是新建事务,挂起当前事务 | 独立日志记录、审计 |
NESTED | 当前有事务则创建嵌套事务(Savepoint) | 批量处理中的子操作 |
SUPPORTS | 有事务则加入,没有则非事务执行 | 查询方法 |
NOT_SUPPORTED | 非事务执行,挂起当前事务 | 不需要事务的操作 |
MANDATORY | 当前必须存在事务,否则抛异常 | 必须在事务中调用的方法 |
NEVER | 当前不能存在事务,否则抛异常 | 确保非事务上下文 |
传播级别实战示例
@Service
public class PaymentService {
@Autowired
private PaymentRepository paymentRepository;
@Autowired
private AuditLogService auditLogService;
@Transactional(propagation = Propagation.REQUIRED)
public void processPayment(PaymentRequest request) {
Payment payment = new Payment(request);
paymentRepository.save(payment);
// 审计日志使用独立事务,即使支付回滚也要记录
auditLogService.logPaymentAttempt(request);
}
}
@Service
public class AuditLogService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logPaymentAttempt(PaymentRequest request) {
// 独立事务:即使外层事务回滚,审计日志也会提交
auditLogRepository.save(new AuditLog("PAYMENT_ATTEMPT", request.toString()));
}
}隔离级别
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 性能 |
|---|---|---|---|---|
READ_UNCOMMITTED | 可能 | 可能 | 可能 | 最高 |
READ_COMMITTED | 不会 | 可能 | 可能 | 高 |
REPEATABLE_READ | 不会 | 不会 | 可能 | 中 |
SERIALIZABLE | 不会 | 不会 | 不会 | 最低 |
// 对账场景:需要可重复读,避免同一事务中两次查询结果不一致
@Transactional(isolation = Isolation.REPEATABLE_READ)
public ReconciliationResult reconcile(String batchId) {
BigDecimal totalBefore = orderRepository.sumAmount(batchId);
// 执行对账逻辑...
BigDecimal totalAfter = orderRepository.sumAmount(batchId);
// REPEATABLE_READ 保证 totalBefore == totalAfter
return new ReconciliationResult(totalBefore, totalAfter);
}回滚规则
Spring 默认只对 未检查异常(RuntimeException 及其子类)和 Error 进行回滚,对检查异常(Exception)不回滚。
@Transactional(
// 指定需要回滚的异常
rollbackFor = {BusinessException.class, IOException.class},
// 指定不需要回滚的异常
noRollbackFor = {DuplicateKeyException.class}
)
public void transferMoney(String from, String to, BigDecimal amount)
throws BusinessException {
accountRepository.debit(from, amount);
accountRepository.credit(to, amount);
if (amount.compareTo(new BigDecimal("100000")) > 0) {
// 检查异常 - 需要 rollbackFor 声明才会回滚
throw new BusinessException("Large transfer requires approval");
}
}事务实现原理
Spring 事务通过 AOP 代理实现。@Transactional 注解最终由 TransactionInterceptor 处理:
事务同步机制
TransactionSynchronizationManager 允许在事务的各个阶段注册回调:
@Transactional
public void createOrder(OrderRequest request) {
Order order = orderRepository.save(new Order(request));
// 注册事务同步回调
TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronization() {
@Override
public void afterCommit() {
// 事务提交后发送通知(确保数据已持久化)
notificationService.sendOrderConfirmation(order);
}
@Override
public void afterCompletion(int status) {
if (status == STATUS_ROLLED_BACK) {
log.warn("Order creation rolled back: {}", order.getId());
}
}
}
);
}更简洁的方式是使用 @TransactionalEventListener:
// 发布事件
@Transactional
public void createOrder(OrderRequest request) {
Order order = orderRepository.save(new Order(request));
eventPublisher.publishEvent(new OrderCreatedEvent(order));
}
// 监听事务提交后事件
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void onOrderCreated(OrderCreatedEvent event) {
notificationService.sendOrderConfirmation(event.getOrder());
}编程式事务
当需要更精细的事务控制时,可以使用 TransactionTemplate 或 PlatformTransactionManager:
@Service
public class BatchService {
@Autowired
private TransactionTemplate transactionTemplate;
public void processBatch(List<Record> records) {
for (Record record : records) {
transactionTemplate.execute(status -> {
try {
processRecord(record);
return true;
} catch (Exception e) {
status.setRollbackOnly();
log.error("Failed to process record: {}", record.getId(), e);
return false;
}
});
}
}
}常见陷阱
1. 自调用导致事务失效
@Service
public class UserService {
// 事务不会生效!自调用不经过代理
public void registerUser(User user) {
this.saveUser(user); // 直接调用,绕过代理
}
@Transactional
public void saveUser(User user) {
userRepository.save(user);
}
}2. 异常被吞掉导致不回滚
@Transactional
public void processOrder(Order order) {
try {
orderRepository.save(order);
inventoryService.reduce(order);
} catch (Exception e) {
// 异常被 catch,Spring 无法感知,事务不会回滚!
log.error("error", e);
}
}3. 非 public 方法上的 @Transactional
Spring AOP 代理只能拦截 public 方法,在 protected、private、package-private 方法上标注 @Transactional 不会生效。
4. 多数据源事务
跨数据源操作无法通过单个 @Transactional 保证一致性,需要引入分布式事务方案(如 Seata、JTA)。
总结
Spring 事务管理通过 PlatformTransactionManager 抽象层和 AOP 代理机制,提供了简洁而强大的事务管理能力。掌握传播级别、隔离级别、回滚规则的配置,理解事务代理的工作原理,并警惕自调用失效、异常吞没等常见陷阱,是编写可靠事务代码的关键。
贡献者
更新日志
9f6c2-feat: organize wiki content and refresh site setup于