web-dev-qa-db-ja.com

JPAでトランザクションをロールバックする方法は?

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に関連付けられているトランザクションを返しますか?

5
JavaTechnical
  1. Spring AOPを使用してトランザクションを管理し、構成とアノテーションが正しく使用されている場合、デフォルトの効果は、ランタイム例外が発生したときにトランザクションがロールバックされることです。

  2. トランザクションを手動で管理した場合は、次のようにトランザクションをロールバックできます。

    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

8
huangyp

以下のように@TransactionalとマークされたメソッドからRuntimeExceptionをスローすると、ロールバックされます。

デフォルトでは、すべてのRuntimeExceptionsはトランザクションをロールバックしますが、チェックされた例外は次のことを行いません。

@Transactional(rollbackFor={MyRuntimeException.class, AnotherRuntimeException.class})
public SomeVal someTransactionalMethod(){
   ...
}
4
PKumar

例外をキャッチしないでください。それを泡立たせてください。トランザクションメソッド呼び出しからランタイム例外がスローされた場合、Springはトランザクションを自動的にロールバックします。そして、発信者は、すべてがうまくいったと考えるのではなく、少なくとも何か悪いことが起こったことを知るでしょう。

とにかく、ほとんどの例外はフラッシュ時に発生し、フラッシュは主にコミットの直前、Springトランザクションインターセプターで発生するため、catchブロックはおそらく何もキャッチしません。エンティティを永続化しても、挿入クエリはすぐには実行されないことに注意してください。トランザクションが終了する前に、挿入を実行する必要があることをHibernateに通知するだけです。

1
JB Nizet

トランザクションをロールバックするには、@ 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ブロックを使用せず(つまり、例外をキャッチしない)、例外を伝播させます。

0
mohammed saquib