首先,我会注意到我使用Spring + Hibernate作为我的JPA2实现。我的应用程序配置了一个JpaTransactionManager和一个HibernateJpaDialect。原子性的嵌套事务(Propogation.REQUIRED_NEW/Propogation.NESTED)
我有一个功能来关闭一个单元,并且我有一个功能可以关闭多个单元。单元停用工作会调用外部服务,如果该调用超时或返回错误状态,则会引发异常。如果单个单元停用失败(无论是通过此外部服务调用还是因为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
的问题,我会遇到问题。我想要的是使用现有的deactivateUnit
和activateUnit
函数的原子reactivation
任务,例如,如果deactivateUnit
或activateUnit
导致回滚,则整个函数将回滚。
我在这个naiive尝试不起作用:
@Transactional(propogation=Propogation.REQUIRES_NEW, rollbackFor=MyException.class)
public void reactivateUnit(String newName, String oldName) throws MyException{
deactivateUnit(oldName);
activateUnit(newName);
}
如果activateUnit
回滚,deactivateUnit
没有。
我想也许我应该改变传播和停用的传播到NESTED
,但是这并不保留函数的回滚行为。
我有点失落,所以我会很感激任何帮助!