13

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仕様の各実装に固有ですか?

情報やガイダンスをありがとうございました。

4

3 に答える 3

5

getTransaction() の使用は、JPA と EclipseLink で機能します (これが私たち自身のテストの仕組みです)。

私の推測では、あなたは何か別の非常に奇妙なことをしていると思います。

Spring を使用していますか、それとも別のレイヤーを使用していますか? テスト用にコード全体と persistence.xml を含めてください。persistence.xml で JTA を使用していないことを確認してください。

于 2012-06-13T13:55:06.970 に答える
1

JPA 仕様 (段落 7.5.4 を参照) には、 を使用しgetTransaction()てトランザクションを開始およびコミットすることを示す明示的な例があります。したがって、コードは問題ないはずです。

あなたのテストは、2 つの異なるオブジェクトを取得することを示していますが、それは同じトランザクションが使用されていないという意味ではありません。返されたオブジェクトは、単一の実際のトランザクション オブジェクトへの単なるプロキシである可能性があります。

または、 の下に隠されているコード内でトランザクションがコミットまたはロールバックされている可能性があります// make some changes

于 2012-06-12T21:58:23.610 に答える