使用 TransactionTemplate
等类和 API 手动管理事务,控制事务的新建、提交、回滚等过程
方式一:使用 TransactionTemplate
(推荐方式)
@Service
public class OrderService {
private final TransactionTemplate transactionTemplate;
private final OrderRepository orderRepository;
private final InventoryRepository inventoryRepository;
public OrderService(PlatformTransactionManager txManager,
OrderRepository orderRepository,
InventoryRepository inventoryRepository) {
this.transactionTemplate = new TransactionTemplate(txManager);
this.orderRepository = orderRepository;
this.inventoryRepository = inventoryRepository;
}
public void createOrder(Order order) {
transactionTemplate.execute(status -> {
try {
// 操作1: 保存订单
orderRepository.save(order);
// 操作2: 扣减库存
inventoryRepository.deductStock(order.getProductId(), order.getQuantity());
return "SUCCESS";
} catch (Exception e) {
status.setRollbackOnly(); // 标记回滚
throw new RuntimeException("Transaction rolled back", e);
}
});
}
}
方式二:使用 PlatformTransactionManager
(精细控制)
@Service
public class PaymentService {
private final PlatformTransactionManager txManager;
private final PaymentRepository paymentRepository;
public PaymentService(PlatformTransactionManager txManager, PaymentRepository paymentRepository) {
this.txManager = txManager;
this.paymentRepository = paymentRepository;
}
public void processPayment(Payment payment) {
// 定义事务属性(传播行为、隔离级别)
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
TransactionStatus status = txManager.getTransaction(definition);
try {
// 业务操作
paymentRepository.save(payment);
// 模拟外部服务调用(若失败需回滚)
if (!externalPaymentGateway.charge(payment)) {
throw new RuntimeException("Payment failed");
}
txManager.commit(status);
} catch (Exception e) {
txManager.rollback(status);
throw e;
}
}
}
为什么不建议用声明式事务?
1)粒度不可控,最低是方法级别,容易造成大事务
2)使用不当,可能造成事务回滚不完全造成业务故障,如方法中调用了第三方接口,接口调用不能回滚
3)失效场景众多,一不小心就会造成事务失效