2012-01-26 67 views
1

首先,我会注意到我使用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的问题,我会遇到问题。我想要的是使用现有的deactivateUnitactivateUnit函数的原子reactivation任务,例如,如果deactivateUnitactivateUnit导致回滚,则整个函数将回滚。

我在这个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,但是这并不保留函数的回滚行为。

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

回答

0

在这种情况下,我认为您不能使用最初注释的deactivateUnit函数。您可能需要尝试使用REQUIRES_NEW调用未标注的帮助函数的包装函数。然后你也可以在你的reactivateUnit方法中调用helper函数。