使用 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)失效场景众多,一不小心就会造成事务失效