原子性的嵌套事务(Propagation.REQUIRES_NEW / Propagation.NESTED)

时间:2012-01-26 22:23:37

标签: hibernate spring transactions jpa-2.0 spring-transactions

首先,我会注意到我正在使用Spring + Hibernate作为我的JPA2实现。我的应用程序配置了JpaTransactionManager和HibernateJpaDialect。

我有一个功能来停用一个单元,我有一个功能,包括停用多个单元。单元停用工作会调用外部服务,如果该调用超时,或者返回错误状态,则会引发异常。如果单个单元停用失败(通过此外部服务调用,或者由于RuntimeException),我想回滚那个单元的事务。

我能够使用Propogation.REQUIRES_NEW实现这一目的,基本如下:

@Transactional
public void deactivateUnits(List<String> names){
    for(String name : names){
        deactivateUnit(name);
    }
}
@Transactional(propogation=Propogation.REQUIRES_NEW, rollbackFor=MyException.class)
public void deactivateUnit(String name) throws MyException{
    ..snip..
    //Some code that throws MyExceptions or RuntimeExceptions
    ..snip..
}

这非常有效。

这种风格也非常适合激活。

@Transactional
public void activateUnits(List<String> names){
    for(String name : names){
        activateUnit(name);
    }
}
@Transactional(propogation=Propogation.REQUIRES_NEW, rollbackFor=MyException.class)
public void activateUnit(String name) throws MyException{
    ..snip..
    //Some code that throws MyExceptions or RuntimeExceptions
    ..snip..
}

但是到了reactivation的时候我遇到了问题。我想要的是使用现有reactivationdeactivateUnit函数的原子activateUnit任务,如果deactivateUnitactivateUnit导致回滚,整个函数将回滚。

我对此的直接尝试不起作用:

@Transactional(propogation=Propogation.REQUIRES_NEW, rollbackFor=MyException.class)
public void reactivateUnit(String newName, String oldName) throws MyException{
    deactivateUnit(oldName);
    activateUnit(newName);
}

如果activateUnit回滚,则deactivateUnit不回滚。

我想也许我应该将激活和停用的传播更改为NESTED,但这不会保留函数的回滚行为。

我有点失落,所以我很感激任何帮助!

1 个答案:

答案 0 :(得分:0)

在这种情况下,我认为您无法使用最初注释的deactivateUnit函数。您可能必须尝试使用​​包装函数,REQUIRES_NEW调用一个未注释的辅助函数。然后,您还可以在您的reactivateUnit方法中调用辅助函数。