Springフレームワークによって維持されているEntityManager
オブジェクトがあり、このような_@PersistenceContext
_アノテーションを使用して必要なDAOクラスに挿入します。
_@PersistenceContext(unitName="entityManager")
private EntityManager em;
_
これらのDAOクラスを使用して、このようなものをデータベースに保存します。
_class MyClass
{
@Resource(name="myDao")
private MyDao dao;
@Resource(name="myAnotherDao")
private MyAnotherDao anotherDao;
public void save(String s1,String s2)
{
try
{
MyEntity m=new MyEntity();
m.setName(s1);
// .. and so on ..
XYZ x=new XYZ();
x.setDEF(s2);
anotherDao.save(x);
m.setXYZ(x);
// .. some other stuff .. //
dao.saveEntity(m);
}
catch(Exception e)
{
// I would like to rollback the transaction
}
}
}
_
ここで、両方のdaosは、@PersistenceContext(unitName="entityManager")
を介して注入された同じEntityManager
を使用します。ここで、setXYZ()
の後に例外が発生した場合、保存されたXYZ
エンティティもロールバックしたいと思います。しかし、どうすればそこからEntityManager
を取得できますか?
すべてのdaosが同じオブジェクトを保持している場合、EntityManager
クラスのgetTransaction().rollback()
メソッドを呼び出すことはできますか? getTransaction()
は、新しいトランザクションまたは現在EntityManager
に関連付けられているトランザクションを返しますか?
Spring AOPを使用してトランザクションを管理し、構成とアノテーションが正しく使用されている場合、デフォルトの効果は、ランタイム例外が発生したときにトランザクションがロールバックされることです。
トランザクションを手動で管理した場合は、次のようにトランザクションをロールバックできます。
EntityManager em = createEntityManager();
try {
em.getTransaction().begin();
// Do something with the EntityManager such as persist(), merge() or remove()
em.getTransaction().commit();
} catch(Exception e) {
em.getTransaction().rollback();
}
em.close();
詳細については、次を参照してください: http://en.wikibooks.org/wiki/Java_Persistence/Transactionshttp://www.developerscrappad.com/547/Java/java-ee/ejb3- x-jpa-when-to-use-rollback-and-setrollbackonly /#sthash.jx3XlK5m.dpuf
以下のように@TransactionalとマークされたメソッドからRuntimeExceptionをスローすると、ロールバックされます。
デフォルトでは、すべてのRuntimeExceptionsはトランザクションをロールバックしますが、チェックされた例外は次のことを行いません。
@Transactional(rollbackFor={MyRuntimeException.class, AnotherRuntimeException.class})
public SomeVal someTransactionalMethod(){
...
}
例外をキャッチしないでください。それを泡立たせてください。トランザクションメソッド呼び出しからランタイム例外がスローされた場合、Springはトランザクションを自動的にロールバックします。そして、発信者は、すべてがうまくいったと考えるのではなく、少なくとも何か悪いことが起こったことを知るでしょう。
とにかく、ほとんどの例外はフラッシュ時に発生し、フラッシュは主にコミットの直前、Springトランザクションインターセプターで発生するため、catchブロックはおそらく何もキャッチしません。エンティティを永続化しても、挿入クエリはすぐには実行されないことに注意してください。トランザクションが終了する前に、挿入を実行する必要があることをHibernateに通知するだけです。
トランザクションをロールバックするには、@ Transactionアノテーションを使用できます。メソッドレベルまたはクラスレベルで実装できます。
メソッドレベルの例:
@Transactional(rollbackFor = {YourDesiredException.class, SomeOtherException.class})
void yourMethod(datatype param1,...){
//your transaction that may throw exception
}
クラスレベルの例:
@Transactional(rollbackFor = {YourDesiredException.class, SomeOtherException.class})
public class SomeClass throws YourDesiredException{
void method1(){
//transaction 1
}
void method2(){
//transaction 2
}
}
クラスレベルの@Transactional(rollbackFor = Exception.class)は、クラスレベルで発生したすべてのトランザクションをロールバックしますが、メソッドレベルでは、そのメソッドで発生したトランザクションのみをロールバックします。
PS:try-catchブロックを使用せず(つまり、例外をキャッチしない)、例外を伝播させます。