Bootstrap

REQUIRED、REQUIRES_NEW、NESTED的区别

REQUIRED、REQUIRES_NEW、NESTED的区别

文档

  1. Spring事务传播行为的七种类型
  2. Transaction rolled back because it has been marked as rollback-only异常产生的原因
  3. REQUIRED、REQUIRES_NEW、NESTED的区别

三种Spring事务传播类型对比

事务传播类型说明
PROPAGATION_REQUIRED当前存在事务:加入当前事务;
当前不存在事务:创建一个新事务。
PROPAGATION_REQUIRES_NEW当前存在事务:挂起当前事务,创建一个新事务;
当前不存在事务:创建一个新事务。
PROPAGATION_NESTED当前存在事务:创建一个嵌套事务;
当前不存在事务:创建一个新事务。

事务提交、回滚对比

2:REQUIRED2:REQUIRES_NEW2:NESTED
1:REQUIRED
1无异常 + 2异常
[回滚,回滚][回滚,回滚][回滚,回滚]
1:REQUIRED
1无异常 + 2异常,1捕获2异常
[回滚,回滚]
异常1
[提交,回滚][提交,回滚]
1:REQUIRED
1异常 + 2无异常
[回滚,回滚][回滚,提交][回滚,回滚]
1:NO
1无异常 + 2异常
[提交,回滚][提交,回滚][提交,回滚]
  • 第一列表示第一个方法事务类型,NO表示无事务
  • 第一行表示第二个方法事务类型
  • 第一个方法调用第二个方法,两个方法在不同的类,事务均可生效
  • 1无异常 + 2异常,表示第一个方法无异常,第二个方法有异常
  • [提交,回滚],表示第一个方法中的事务提交,第二个方法中事务回滚
  • 异常1:org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

总结

  1. 如果当前无事务,则REQUIRED、REQUIRES_NEW、NESTED三种事务传播类型无区别,效果都是创建一个新事务
  2. 如果当前存在事务,REQUIRED表示加入当前事务。可以理解为整体(方法一和方法二)使用同一个事务标识,同时提交或回滚。即使方法一捕获了方法二的异常,但是方法二抛出了异常,整体事务被标记为回滚了,此时方法一虽然可以继续运行到结束,但最终也是事务回滚,并且会主动抛出异常。
  3. 如果当前存在事务,REQUIRES_NEW表示挂起当前事务,创建一个新事务。方法一与方法二使用不同的事务,互不影响。需要注意的是,如果方法二抛出异常,方法一并没有捕获,导致方法一也抛出异常,此时方法一的事务也会回滚。
  4. 如果当前存在事务,NESTED表示创建一个嵌套事务。嵌套事务可以理解为在事务中创建一个保存点(savepoint),两个方法用同一个事务,调用方法二时,创建一个保存点。方法二抛出异常,则事务内部回退到保存点,只是事务内部进行了部分回退,整体的事务此时并没有提交或回滚,如果方法一捕获了方法二的异常,则事务会提交,因为方法二已提前回退,所以方法二表现为回滚。需要注意的是,如果方法二抛出异常,方法一并没有捕获,导致方法一也抛出异常,此时事务会回滚。

REQUIRED示例

示例1:REQUIRED1无异常 + REQUIRED2异常
  • PropagationServiceAImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToRequired() {
        update1();
        propagationServiceB.required();
    }
    
  • PropagationServiceBImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void required() {
        update3();
        int i = 1 / 0;
    }
    
  • 此时,update1、update3均会回滚

示例2:REQUIRED1无异常 + REQUIRED2异常,REQUIRED1捕获REQUIRED2异常
  • PropagationServiceAImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToRequired1() {
        update1();
        try {
            propagationServiceB.required();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
  • PropagationServiceBImpl.java

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void required() {
        update3();
        int i = 1 / 0;
    }
    
  • 此时,update1、update3均会回滚,并且会抛出org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only异常

示例3:REQUIRED1异常 + REQUIRED2无异常
  • PropagationServiceAImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToRequired2() {
        update1();
        propagationServiceB.required1();
        int i = 1 / 0;
    }
    
  • PropagationServiceBImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void required1() {
        update3();
    }
    
  • 此时,update1、update3均会回滚

示例4:NO无异常 + REQUIRED异常
  • PropagationServiceAImpl.java

    @Override
    public void noToRequired() {
        update1();
        propagationServiceB.required();
    }
    
  • PropagationServiceBImpl.java

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void required() {
        update3();
        int i = 1 / 0;
    }
    
  • 此时,update1提交,update3回滚

REQUIRES_NEW示例

示例1:REQUIRED无异常 + REQUIRES_NEW异常
  • PropagationServiceAImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToRequiresNew() {
        update1();
        propagationServiceB.requiresNew();
    }
    
  • PropagationServiceBImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void requiresNew() {
        update3();
        int i = 1 / 0;
    }
    
  • 此时,update1、update3均会回滚

示例2:REQUIRED无异常 + REQUIRES_NEW异常,REQUIRED捕获REQUIRES_NEW异常
  • PropagationServiceAImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToRequiresNew1() {
        update1();
        try {
            propagationServiceB.requiresNew();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
  • PropagationServiceBImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void requiresNew() {
        update3();
        int i = 1 / 0;
    }
    
  • 此时,update1会提交,update3会回滚

示例3:REQUIRED异常 + REQUIRES_NEW无异常
  • PropagationServiceAImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToRequiresNew2() {
        update1();
        propagationServiceB.requiresNew1();
        int i = 1 / 0;
    }
    
  • PropagationServiceBImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void requiresNew1() {
        update3();
    }
    
  • 此时,update1会回滚、update3会提交

示例4:NO无异常 + REQUIRES_NEW异常
  • PropagationServiceAImpl.java

    @Override
    public void noToRequiresNew() {
        update1();
        propagationServiceB.requiresNew();
    }
    
  • PropagationServiceBImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void requiresNew() {
        update3();
        int i = 1 / 0;
    }
    
  • 此时,update1会提交,update3会回滚

NESTED示例

示例1:REQUIRED无异常 + NESTED异常
  • PropagationServiceAImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNested() {
        update1();
        propagationServiceB.nested();
    }
    
  • PropagationServiceBImpl.java

    @Override
    @Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class)
    public void nested() {
        update3();
        int i = 1 / 0;
    }
    
  • 此时update1、update3均会回滚

示例2:REQUIRED无异常 + NESTED异常,REQUIRED捕获NESTED异常
  • PropagationServiceAImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNested1() {
        update1();
        try {
            propagationServiceB.nested();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
  • PropagationServiceBImpl.java

    @Override
    @Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class)
    public void nested() {
        update3();
        int i = 1 / 0;
    }
    
  • 此时,update1会提交,update3会回滚

示例3:REQUIRED异常 + NESTED无异常
  • PropagationServiceAImpl.java

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void requiredToNested2() {
        update1();
        propagationServiceB.nested1();
        int i = 1 / 0;
    }
    
  • PropagationServiceBImpl.java

    @Override
    @Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class)
    public void nested1() {
        update3();
    }
    
  • 此时,update1、update3均会回滚

示例4:NO无异常 + NESTED异常
  • PropagationServiceAImpl.java

    @Override
    public void noToNested() {
        update1();
        propagationServiceB.nested();
    }
    
  • PropagationServiceBImpl.java

    @Override
    @Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class)
    public void nested() {
        update3();
        int i = 1 / 0;
    }
    
  • 此时,update1会提交,update3会回滚

;