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

相关推荐
吴名氏.16 分钟前
Java转AI Agent教程(第十三周)混合检索与重排
java·数据库·人工智能·ai·ai agent
爱码少年29 分钟前
Springboot下如何将CSV文件数据导入H2、Mysql数据库表
数据库·mysql·csv
.痞老板.1 小时前
java ee--多线程(进阶)
java·java-ee
可乐ea2 小时前
智能体记忆该拆成几层:笔记、记忆表示与注入上下文
服务器·数据库·笔记·ai智能体·提示词工程·上下文工程·记忆系统
深入云栈3 小时前
Netty 4.2.x 源码深度解析 (二十三):ByteBuf 核心设计 —— 索引、类型与零拷贝
java·后端·架构
阿义有问题3 小时前
MySQL 迁移达梦全流程实战:DTS 七步图解 + 对象名全大写适配(附踩坑清单)
数据库
wang_shu_mo_ran4 小时前
MyBatis 从入门到进阶(一)
java·spring·mybatis
量化分析码农5 小时前
股票历史数据的复权参数对照:多级别返回的字段与数值差异
java·javascript·后端
猫猫不是喵喵.5 小时前
从0到1创建一个微服务项目
java·数据库·微服务·1024程序员节
瑞雪兆丰年兮5 小时前
JavaWeb-day13-SpringBootWeb事务管理&AOP
java·开发语言·springboot·javaweb·事务·web·aop