2017-02-01 2 views
0

を使用してトランザクションを再開することはできません:iが1 EntityManagerを使用して二回のトランザクションをオープンしようとしているEntityManger

EntityManagerFactory emf = Persistence.createEntityManagerFactory("HelloWorldPU"); 
     EntityManager em = emf.createEntityManager(); 

     Message message0 = new Message(); 
     message0.setText("Hi!!"); 
     em.getTransaction().begin(); 
     em.persist(message0); 
     em.getTransaction().commit(); 
     em.close(); 

     Message message1 = new Message(); 
     message1.setText("Bye!!"); 

     System.out.println("i'm here"); 
     em.getTransaction().begin(); 
     em.persist(message1); 
     em.getTransaction().commit(); 
     em.close(); 

と例外を取得:

を私は「ここ

スレッドでの例外ですメイン "java.lang.IllegalStateException:or[email protected]31e4bb20が閉じている

私の推測です:閉鎖されたEntityManagerから別のトランザクションを取得することはできません。しかしJPA Specは言う:

EntityManager.close方法は、その永続コンテキストや他のリソースを解放するために、エンティティ・マネージャを閉じます。 closeを呼び出した後、アプリケーションはgetTransactionisOpen以外のインスタンスでそれ以上のメソッドを呼び出さないでください。そうでないとIllegalStateExceptionがスローされます。トランザクションがアクティブなときにcloseメソッドが呼び出されると、トランザクションが完了するまで持続コンテキストが管理されたままになります。

誰かが私が間違っていると説明できますか? getTransactionを呼び出す可能性はありません、私はこのトランザクションを使用することができ、トランザクションのメソッドを呼び出すことができますか?

ありがとうございます。答えを

UPDATE

おかげで、これらは私のために最も有用である:

1:

あなたが近くに呼び出すまで、あなたはEntityManagerを使用することができます、はい。 「再オープン」メソッドはありません。 EntityManagerを作成する安価な操作である - ニール ストックトン13分前

2:あなたは、トランザクションがアクティブであるかどうかを確認するためにgetTransactionを呼び出すことができます

。 Yu は、アクティブなtx(ドキュメント 状態)と終了後にコミットするEntityManagerを閉じることもできます。したがって、あなたは getTransactionと呼ぶことができます。 - M. Deinum 9分前

+1

ドキュメントはかなり明確です.... *アプリケーションは、* ...あなたがいない、閉じたエンティティマネージャで何かを保持しようとしている、getTransactionといるisOpen以外のEntityManagerインスタンス上の任意の更なるメソッドを呼び出す必要がありません許可されます。エンティティマネージャで一度だけcloseを呼び出す必要があります。その後、私はgetTransactionを呼び出すことができますし、それを使用することはできませんなぜ –

+0

OK、しかし、私は理解できないことはありますか? –

+0

なぜEntityManagerを終了してANYメソッドを呼び出そうとしますか?後でそれをもう一度閉じようとするのはもちろんです。 –

答えて

1

現実には、最初のclose()呼び出しは不要です。あなたが効果的に達成したいのは、完全に有効な2つの独立したトランザクションを持つことです。これを行うには2つの基本的な方法があります。

1)トランザクションをコミットし、同じエンティティマネージャインスタンスで新しいトランザクションを開始します。私は、エンティティ・マネージャが住んでどのくらいの時間を示すためにインデントを乱用例:

EntityManager em = emf.createEntityManager(); 

     Message message0 = new Message(); 
     message0.setText("Hi!!"); 
     em.getTransaction().begin(); 
     em.persist(message0); 
     em.getTransaction().commit(); 

     // no close here 

     Message message1 = new Message(); 
     message1.setText("Bye!!"); 

     System.out.println("i'm here"); 
     em.getTransaction().begin(); 
     em.persist(message1); 
     em.getTransaction().commit(); 

em.close(); 

2)エンティティマネージャを閉じて、コメントで言ったように新しいものが(かなり安いです作成)

EntityManager em = emf.createEntityManager(); 

     Message message0 = new Message(); 
     message0.setText("Hi!!"); 
     em.getTransaction().begin(); 
     em.persist(message0); 
     em.getTransaction().commit(); 

em.close(); 


// create new EntityManager 
em = emf.createEntityManager(); 

     Message message1 = new Message(); 
     message1.setText("Bye!!"); 

     System.out.println("i'm here"); 

     em.getTransaction().begin(); 
     em.persist(message1); 
     em.getTransaction().commit(); 

em.close(); 

どのオプションを選択するかは、これが含まれているアプリケーション機能のさらなる設計によって決まります。オプション1)は、よりキャッシュフレンドリであり、トランザクション間で第1レベルのキャッシュを維持する可能性が高くなります。これは、トランザクションとデータソース内のデータの変更の間の遅延、トランザクション間でem.clear()への呼び出しを解決することができるものがある場合は無効にならキャッシュにキャッシュされたエンティティのリスクがあります。私は、トランザクションバッチ処理のロジックを実装していたときに

I)はオプション2のために行く傾向がある、と言う:小さな塊で処理し、コミットされるレコードを大量にポンプのファイルのインポート・ロジックを。それ以外の場合、オプション1)は通常うまく動作します。

-1

あなたのコードに次の変更を作ってみましょう:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("HelloWorldPU"); 
     EntityManager em = emf.createEntityManager(); 

    Message message0 = new Message(); 
    em.getTransaction().begin(); 
    message0.setText("Hi!!"); 
    em.persist(message0); 
    em.getTransaction().commit(); 
    em.close(); 
EntityManagerFactory emf1 = Persistence.createEntityManagerFactory("HelloWorldPU"); 
      EntityManager em1 = emf.createEntityManager(); 
    Message message1 = new Message(); 
    em1.getTransaction().begin(); 
    message1.setText("Bye!!"); 

    System.out.println("i'm here"); 

    em1.persist(message1); 
    em1.getTransaction().commit(); 
    em1.close(); 

てみてくださいし、EMを閉じる​​と、新しいものを開く/作成する必要があり戻します!。

+0

EMFを複数回作成すると、アプリケーションが非常に遅く実行されます。また、EMFを閉じているわけでもありません... –

関連する問題