2011-02-04 27 views
11

私は現在@PostPersist@PostUpdateで作業しています。これらのトリガーでは、追加のエンティティを永続化しています。問題は、同じトランザクション内のトリガーであり、そうでない場合は、強制することが可能なのでしょうか?JPA/@PostPersist @PostUpdate - トランザクション

私にとっては、この方法で動作します。 ログを調べている間、トランザクションは存在しません(トリガーが起動する直前にコミットされています)。これにより、データベースに追加のエンティティを保存することができなくなりました(REQUIRES_NEWは注入されたBeanの永続メソッドには反映されません)。 REQUIRED属性は完全に無視され、MANDATORY属性は例外をスローしません。

JUnitで問題になる可能性があります(私は開発段階にあり、完全なenvでの動作をテストしていません)。

ロールバックが@PostPersistおよび@PostUpdateより前に発生すると、これらの操作も確実にロールバックされるように、このトリガーでトランザクションを拡張することはできません。

はPostPersistイベントの発火は実体がコミット成功を行っていることを示すものではありません

敬具、 P.

+0

ねえ。私がテストすると、リスナー内のすべての操作がマスター操作の同じトランザクション内にあることがわかります。 @PostUpdateアノテーションを使用してリスナーをマークします。 – Scarlett

答えて

11

、任意の助けを事前にありがとうございます。トランザクションは、イベントの開始後、コミットが成功する前にロールバックされる可能性があります。 あなたはPostPersistでの取引に使用されるエンティティマネージャを取得し、このようsomehtingを行う場合は、次の

@PostPersist 
void someMethod() { 
    EntityManager em = null; 
    em = getEntityManagerUsedInTransaction(); 
    EntityTransaction et = em.getTransaction(); // should return the current transaction 
    if (et.isActive()) { 
    // do more db stuff 
    } 
} 

NB:それは私が生涯のイベントトリガを使用していた「カントーだけ憶測(ですので、私はこれを試していません他のもののために広範囲に)。 これは良い考えだとは思わないと付け加えなければなりません。 PostPersistを使用して、他のエンティティを永続化し、別のトランザクションでそれを実行するようにフラグを立てます。

10

あなたが春を使用している場合は、常に、そのようなあなたの現在実行中のトランザクションのコミットなどのイベントにコールバックするためにあなたの現在のトランザクションマネージャとTransactionSynchronizationを登録できます。

@PostPersist 
void onPersist() { 
    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() { 

     @Override 
     public void beforeCommit(boolean readOnly) { 
     // do work 
     } 
    }); 
    }  
} 

TransactionSynchronization後にコールバックを提供しますトランザクションは正常にコミットされ、トランザクションが完了する前後にコミットされます。

トランザクションがコミットまたはロールバックされたかどうかを調べる必要がある場合は、afterCompletion(int status)を使用してください。

詳細はTransactionSynchronization's JavaDocをご覧ください。

-1

JPA内部コールバックメソッド 内部コールバックメソッドは、エンティティクラス内で定義されたメソッドです。たとえば、以下のエンティティ・クラスが空の実装とサポートされているすべてのコールバックメソッドを定義しています

@Entity 
public static class MyEntityWithCallbacks { 
    @PrePersist void onPrePersist() {} 
    @PostPersist void onPostPersist() {} 
    @PostLoad void onPostLoad() {} 
    @PreUpdate void onPreUpdate() {} 
    @PostUpdate void onPostUpdate() {} 
    @PreRemove void onPreRemove() {} 
    @PostRemove void onPostRemove() {} 
} 

内部のコールバックメソッドは、常にvoidを返しと引数を取るべきではありません。名前とアクセスレベル(公開、保護、パッケージ、プライベート)は任意ですが、静的であってはいけません。

注釈コールバックメソッドが呼び出されたときに指定:

@PrePersist - before a new entity is persisted (added to the EntityManager). 
@PostPersist - after storing a new entity in the database (during commit or flush). 
@PostLoad - after an entity has been retrieved from the database. 
@PreUpdate - when an entity is identified as modified by the EntityManager. 
@PostUpdate - after updating an entity in the database (during commit or flush). 
@PreRemove - when an entity is marked for removal in the EntityManager. 
@PostRemove - after deleting an entity from the database (during commit or flush). 

エンティティ・クラスは、任意のサブセットまたはライフサイクルイベントの組み合わせが、同じイベントのない複数のコールバックメソッドのコールバックメソッドを含むことができます。ただし、複数のコールバックイベントに対して、同じメソッドを複数の注釈でマークすることで使用できます。

デフォルトでは、スーパークラスのコールバックメソッドはサブクラスのエンティティオブジェクトに対して呼び出され、そのコールバックメソッドはサブクラスによってオーバーライドされます。

実装の制限 エンティティライフサイクルイベント(まだ進行中)を起動する元のデータベース操作との競合を回避するため、コールバックメソッドはEntityManagerまたはQueryメソッドを呼び出すべきではなく、他のエンティティオブジェクトにアクセスしないでください。

アクティブなトランザクション内でコールバックメソッドが例外をスローすると、トランザクションはロールバック用としてマークされ、その操作のためのコールバックメソッドはそれ以上呼び出されません。

関連する問題