SpringBoot 手动控制事务,即编程式事务

前置知识

  • Spring 事务默认只在发生未捕获的 RuntimeException 时才回滚
  • Spring AOP 异常捕获需要被拦截的方法显式的抛出异常。默认情况下 AOP 只捕获 RuntimeException 类的异常,但可以通过配置来捕获特定的异常

手动控制事务案例

在日常开发中,如果没办法使用 @Transactional 注解时(比如手动进行了 try catch、多线程操作、设置回滚点等)就得进行手动的编程式事务管理了

1.手动回滚try catch的异常处理

在try catch块中如果需要对事务进行回滚,就得强制使用Spring提供的事务切面类 TransactionAspectSupport

@Transactional
public void saveOmsOutboundOrder(OmsOutboundOrder order) {
    try {
        omsOutboundOrderDao.save(order);

        //模拟异常
        int sum = 1 / 0;
    }catch (Exception e){
        log.error("saveOmsOutboundOrder出现异常: ", e);

        //手动强制回滚事务
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
}

2.回滚到保存点

如果开启了一个事务,并且已经输入了很多的语句时,如果忽然发现上一条语句有问题,可以用 rollback 语句来让数据库状态恢复到事务执行之前的样子,然后一切再重来。因为这个问题,MySQL 提出了一个保存点 savepoint 的概念,就是在事务对应的数据库语句中打几个点,在调用 rollback 语句时能指定回滚到哪个点,而不是最初的原点

@Transactional
public void saveOmsOutboundOrder(OmsOutboundOrder order,OmsOutboundOrderDetail orderDetail) {

    Object savepoint = null;
    try {
        omsOutboundOrderDao.save(order);

        //设置保存点
        savepoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
        orderDetail.setOrderId(order.getId());
        omsOutboundOrderDao.save(orderDetail);

        //模拟异常
        int sum = 1 / 0;
    }catch (Exception e){
        log.error("saveOmsOutboundOrder出现异常: ", e);

        //手动强制回滚事务到保存点
        TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savepoint);
    }
}

3.DataSourceTransactionManager

Spring 的事务处理中,通用的事务处理流程是由抽象事务管理器 AbstractPlatformTransactionManager 来提供的,由 PlatformTransactionManager 的具体实现类来实现

@Autowired
private DataSourceTransactionManager transactionManager;

//@Autowired
//private DataSourceTransactionManager transactionManager;

@Transactional
public void saveOmsOutboundOrder(OmsOutboundOrder order) {

    //TransactionStatus transaction = transactionManager.getTransaction(TransactionDefinition.withDefaults());
   
    DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
    definition.setPropagationBehaviorName("PROPAGATION_REQUIRED");
    TransactionStatus transaction = transactionManager.getTransaction(definition);

    try {
        omsOutboundOrderDao.save(order);

        //模拟异常
        int sum = 1 / 0;

        transactionManager.commit(transaction);
    }catch (Exception e){
        log.error("saveOmsOutboundOrder出现异常: ", e);

        //手动控制回滚异常
        transactionManager.rollback(transaction);
    }
}
posted @ 2024-03-30 21:46  伊文小哥  阅读(2013)  评论(0编辑  收藏  举报