2011-09-01 8 views
9

J2EEアプリケーションでは、EJB-3ステートフルBeanを使用して、フロントコードが永続エンティティ(JPA-2で管理)を作成、変更、保存できるようにします。拡張PersistenceContextでEntityManagerを手動でflush()する必要があるのはなぜですか?

それはこのようなものになります。早すぎるコミットを避けるために、

@LocalBean 
@Stateful 
@TransactionAttribute(TransactionAttributeType.NEVER) 
public class MyEntityController implements Serializable 
{ 
    @PersistenceContext(type = PersistenceContextType.EXTENDED) 
    private EntityManager em; 

    private MyEntity current; 

    public void create() 
    { 
     this.current = new MyEntity(); 
     em.persist(this.current); 
    } 

    public void load(Long id) 
    { 
     this.current = em.find(MyEntity.class, id); 
    } 

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
    public void save() 
    { 
     em.flush(); 
    } 
} 

非常に重要な、唯一0​​メソッドは、トランザクション内にあるので、我々はcreate()を呼び出す場合、我々は、データベースに何も挿入しません。

奇妙なことに、save()メソッドでは、実際にデータベースにヒットするには、em.flush()を呼び出す必要があります。実際、私は、em.isOpen()またはem.getFlushMode()と呼ぶこともできますが、「em関連」であることを確認しました。

私はこの点を理解していません。 save()はトランザクション内にあるので、メソッドの最後にトランザクションがコミットされると考えて、永続的なエンティティマネージャが自動的にフラッシュしました。手動でフラッシュする必要があるのはなぜですか?あなたが拡張永続コンテキストを使用する場合は

おかげで、 ザビエル

+0

'flush()'は必要ありません。 'joinTransaction()'はあなたのトランザクションメソッドに変更を保存するのに十分なはずです。 –

答えて

7

の完全な説明を見つけることができるし、金属に、トランザクションで実際に使用それあなたまで質問にEntityManagerのために登録されたオブジェクトは存在しません。

これらのオブジェクトのいずれかを作成してflush()を作成し、javax.transaction.TransactionSynchronizationRegistryまたはjavax.transaction.Transactionに登録します。アクティブなトランザクションがないかぎり、これは実行できません。

これは、その長短です。

はい、アプリケーションサーバーはステートフルBeanに与えたリソースのリストを保持し、ステートフルBeanが開始または参加する可能性のあるすべてのトランザクションで自動的に登録できます。どの取引にどの商品が入るかを決定する。たぶん、異なるパーシスタンスユニットで実行する2つまたは3つの異なるトランザクションがあり、非常に特定のトランザクションに対して拡張パーシスタンスコンテキストでワークを集約している可能性があります。それは本当にデザイン上の問題で、アプリケーションサーバーはそのような決定をアプリ自体に任せておくべきです。

トランザクションで使用すると、トランザクションに登録されます。それが基本契約です。

サイドノートでは、基礎となるのEntityManagerをどのように処理されるかに応じて、EntityManagerのからいかなる永続的な呼び出しがトランザクションの終了時に完全なフラッシュを引き起こすのに十分かもしれません。確かに、flush()が最も直接的かつ明確ですが、persist()、さらにはfind()でも可能です。

+1

あなたの答えを完全に理解するまでには時間がかかりましたが、今は意味があります。ありがとう! –

+0

伝播されない 永続コンテキストのJPA2.1仕様(7.6.4.1永続コンテキスト伝播の要件)からの関連引用: 'エンティティマネージャがJTAトランザクション内で呼び出された場合、永続コンテキストは がJTAトランザクションに関連付けられます'。 –

0

は、非トランザクションメソッド内で行わ管理対象エンティティ上のすべての操作がデータベースに書き込まれるようにキューイングされます。トランザクションコンテキスト内のエンティティマネージャでflush()を呼び出すと、キューに入れられたすべての変更がデータベースに書き込まれます。つまり、トランザクションメソッドがあるという事実は、メソッドが終了すると(CMTのように)変更自体をコミットしませんが、フラッシングエンティティマネージャは実際には行います。あなたは、直接であるためには、このプロセスhere

+2

私はこのチュートリアルを見ましたが、ちょっと混乱しているようです。 これは、 "これは、永続的、マージ、または削除するメソッドが実際にはJDBCの実行をもたらさないため、手動でEntityManager.flushを呼び出すまでデータベースの更新が行われないことを意味します。あなたのためのポイント:) しかし、2番目の例では、 "never()updateはcheckout()メソッドの最後にコミットされます"というメッセージが表示され、このcheckout()は空で、フラッシュされません。この例をどう説明することができますか? また、Real World JavaEE Patterns Adam Bienでは、GateWayパターンにも空の保存メソッドがあります:http://tinyurl.com/3o96xoh(スライド67)。 –

0

クライアントがセッション(拡張スコープ)で「いつ」終了したかを知る方法がないため。

関連する問題