EclipseLink2.3.0を使用しています。次のような単体テスト(したがって、コンテナーの外部、JTAなし)から呼び出しているメソッドがあります。
EntityManager em = /* get an entity manager */;
em.getTransaction().begin();
// make some changes
em.getTransaction().commit();
変更はデータベースに永続化されておらず、これを長い間調べて、EntityManager.getTransaction()が両方の呼び出しで同じものではなく実際に新しいEntityTransactionを返していることに最終的に気付きました。その結果、最初の呼び出しで新しいトランザクションが作成されて開始され、2番目の呼び出しで別のトランザクションが作成されてコミットされます。最初のトランザクションはコミットされなかったため、変更は保存されません。これを次のように確認しました:
log.info(em.getTransaction().toString());
log.info(em.getTransaction().toString());
その結果、次のログメッセージが表示されました。
INFO: org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl@1e34f445
INFO: org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl@706a4d1a
2つの異なるインスタンスがあることを確認する2つの異なるオブジェクトID。コードを次のように変更します。
EntityManager em = /* get an entity manager */;
EntityTransaction tx = em.getTransaction();
tx.begin();
// make some changes
tx.commit();
...問題を解決しました。コードを実行すると、データベース作業を行うために生成されたSQLステートメントが表示され、データベースを見ると、データが変更されています。
トランザクションの管理に使用したコードを推奨する多数のコード例(一般的にはJPA、具体的にはEclipseLink)をオンラインで見たので、この結果に少し驚いていました。私はこれについて具体的に情報を広範囲に検索しましたが、何も見つかりませんでした。どうしたの?
私はJPA仕様で、getTransaction()が何をするかを正確に指定するものを探しましたが、トランザクションが新しいか同じかは特定されていませんでした。これを制御するpersistence.xmlの設定はありますか?動作はJPA仕様の各実装に固有ですか?
情報やガイダンスをありがとうございました。