まず、JPA2の実装としてSpring+Hibernateを使用していることに注意してください。私のアプリケーションは、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
ぶつかります。私が欲しいのは、既存の関数と関数reactivation
を利用するアトミックタスクです。つまり、またはのいずれかがロールバックを引き起こした場合、関数全体がロールバックします。deactivateUnit
activateUnit
deactivateUnit
activateUnit
これに対する私の素朴な試みはうまくいきません:
@Transactional(propogation=Propogation.REQUIRES_NEW, rollbackFor=MyException.class)
public void reactivateUnit(String newName, String oldName) throws MyException{
deactivateUnit(oldName);
activateUnit(newName);
}
activateUnit
ロールバックする場合は、deactivateUnit
しません。
アクティブ化と非アクティブ化の伝播をに変更する必要があるかもしれないと思いましたが、それではNESTED
関数のロールバック動作が維持されません。
少し戸惑っていますので、よろしくお願いします!