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

相关推荐
菲兹园长几秒前
SpringBoot统一功能处理
java·spring boot·后端
阿文弟3 分钟前
MYSQL之索引结构,为何要用B+树
数据库·mysql
一刀到底2119 分钟前
spring ai alibaba 使用 SystemPromptTemplate 很方便的集成 系统提示词
spring·ai alibaba
博睿谷IT99_12 分钟前
MySQL OCP 认证限时免费活动 7 月 31 日 前截止!!!
数据库·mysql·开闭原则
博睿谷IT99_16 分钟前
MySQL OCP和Oracle OCP怎么选?
数据库·mysql·oracle·开闭原则·ocp
一刀到底21126 分钟前
java 多核,多线程,分布式 并发编程的现状 :从本身的jdk ,到 spring ,到其它第三方。
java·分布式·高并发
Kendra91932 分钟前
Docker 容器 - Dockerfile
java·docker·eureka
hnlucky1 小时前
《Zabbix Proxy分布式监控实战:从安装到配置全解析》
数据库·分布式·学习·adb·zabbix·集成学习·proxy模式
Auc241 小时前
Java 原生实现代码沙箱(OJ判题系统第1期)——设计思路、实现步骤、代码实现
java·开发语言·python
Catfood_Eason1 小时前
初识MySQL
数据库·mysql