Spring事务嵌套问题记录

问题描述

今天遇到一个spring事务嵌套的问题:

**Transaction rolled back because it has been marked as rollback-only**

问题复现

ConsumerService.c() 中调用 ProducerService.p()

ProducerService.p()中抛出一个运行时异常

ConsumerService.c()catchp()的异常

代码如下:

public class ProducerServiceImpl implements ProducerService{
    @Autoware
    private UserService userService;
    @Transactional
    @Override
    public void p() {
        //保存
        userService.save(new User());
        //模拟异常
        throw new RuntimeException("eee");
    }
}
public class ConsumerServiceImpl implements ConsumerService{
    @Autoware
    private UserService userService;
    @Autoware
    private ProducerService producerService;
    @Transactional
    @Override
    public void c() {
        //保存
        userService.save(new User());
        //调用p() 并catch
        try{
        producerService.p();
        }catch(Exception e){

        }
    }
}

运行代码报错:

org.springframework.transaction.UnexpectedRollbackException:   Transaction rolled back because it has been marked as rollback-only

问题解决

  1. ProducerService.p()方法的@Transactional删除(没有其他方法调用c()
  2. ProducerService.p()方法上加@Transactional(propagation = Propagation.REQUIRES_NEW)开启新事务
  3. 如果不想改动@Transactional并且想不报错,代码改动如下
    public class ConsumerServiceImpl implements ConsumerService{
       @Autoware
       private UserService userService;
       @Autoware
       private ProducerService producerService;
       @Transactional
       @Override
       public void c() {
           //保存
           userService.save(new User());
           //调用p() 并catch
           try{
           producerService.p();
           }catch(Exception e){
               TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
           }
       }
    }
  4. 如果不想改动@Transactional并且 想让producerService.p();不影响consumerService.c()方法,代码改动如下 (此时c()方法的代码将不会回滚!)
    public class ConsumerServiceImpl implements ConsumerService{
       @Autoware
       private UserService userService;
       @Autoware
       private ProducerService producerService;
       @Transactional
       @Override
       public void c() {
           try{   
               //保存
               userService.save(new User());
               //调用p() 并catch
               try{
                  producerService.p();
               }catch(Exception e){
    
               }
           }catch(Exception e){
                 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
       }
       }
    }

源码分析

todo

原文地址:https://www.cnblogs.com/doagain/p/15068240.html