Spring编程式事务(本地事务)

使用 TransactionTemplate等类和 API 手动管理事务,控制事务的新建、提交、回滚等过程

方式一:使用 TransactionTemplate(推荐方式)

java 复制代码
@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(精细控制)

java 复制代码
@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)失效场景众多,一不小心就会造成事务失效

相关推荐
南极企鹅1 小时前
springBoot项目有几个端口
java·spring boot·后端
清风拂山岗 明月照大江2 小时前
Redis笔记汇总
java·redis·缓存
未来之窗软件服务2 小时前
计算机等级考试—高频英语词汇—东方仙盟练气期
数据库·计算机软考·东方仙盟
lekami_兰2 小时前
MySQL 长事务:藏在业务里的性能 “隐形杀手”
数据库·mysql·go·长事务
xiaoxue..2 小时前
合并两个升序链表 与 合并k个升序链表
java·javascript·数据结构·链表·面试
JQLvopkk2 小时前
C# 轻量级工业温湿度监控系统(含数据库与源码)
开发语言·数据库·c#
忧郁的Mr.Li2 小时前
SpringBoot中实现多数据源配置
java·spring boot·后端
yq1982043011562 小时前
静思书屋:基于Java Web技术栈构建高性能图书信息平台实践
java·开发语言·前端
一个public的class2 小时前
你在浏览器输入一个网址,到底发生了什么?
java·开发语言·javascript
有位神秘人2 小时前
kotlin与Java中的单例模式总结
java·单例模式·kotlin