如何只回滚内部方法而不影响外部方法?

时间:2016-08-11 09:40:31

标签: spring-transactions

@Transactional
public void foo(){
    doSomthing();
    try{
        bar();
    }catch(BizException e){
        logger.warn("call bar failed",e);
        // do some work here
    }
    doSomethingElse();

}
@Transactional
public void bar(){
    // ...
    if(meetSomeCondition){
        throw new BizException(...);
    }
    // ...
}

如果bar抛出BizException,即使在foo中显式捕获异常,在最终它仍然会回滚并抛出异常

org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:720)

并且有一些解决方案,但我发现它对我的情况不可行

e.g。

@Transactional(noRollbackFor=BizException.class)

因为在foo中也会抛出BizException,在这种情况下它应该回滚。

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void bar()

如果明确指定传播为REQUIRES_NEW,则在调用bar()时,它将创建一个新会话,并且仅回滚此会话。但是,如果bar失败,则所有进程都会回滚。

所以现在我的临时解决方案是

public void anotherBarWithoutTransaction(){
    // ...
    if(meetSomeCondition){
        throw new BizException(...);
    }
    // ...
}

@Transactional
public void bar(){ // only add an annotation
    anotherBarWithoutTransaction();
}

在我的上述情况下,我将直接致电anotherBarWithoutTransaction。但它并不是很理想。

1 个答案:

答案 0 :(得分:0)

使用程序化事务管理方式显式创建新事务,例如

@Autowired
private TransactionTemplate transactionTemplate;

transactionTemplate.execute(new TransactionCallbackWithoutResult() {
   protected void doInTransactionWithoutResult(TransactionStatus status) {
       try {
           barService.bar();
       } catch (ApiException e) {
           logger.warn("call bar failed",e);
           status.setRollbackOnly();
       }
   }
});

<bean id="transactionTemplate"
      class="org.springframework.transaction.support.TransactionTemplate">
    <property name="propagationBehaviorName" value="PROPAGATION_REQUIRES_NEW"/>
    <property name="transactionManager" ref="txManager"/>
</bean>

参考:http://docs.spring.io/autorepo/docs/spring/4.2.x/spring-framework-reference/html/transaction.html#transaction-programmatic