2010-11-19 25 views
3

私はShared EntityManager(Springを介してSharedEntityManagerCreatorを使用)を使用するDAOの統合テストを行っています。テストクラスはテスト対象のDAOメソッドと同様に@Transactionalとしてマークされます。テストクラスと次のように私はUserエンティティをretreivingてるDAOの両方でJPA:EntityManager.find()は常に同じキーの同じオブジェクト参照を返しますか?

:私のテストのセットアップで

User user = em.find(User.class, "test"); 

私はユーザーオブジェクトを変更したが、私は見ていませんでしたテストが実行されたときのDAOの変更。 2つの参照は同じオブジェクトを参照していないことが判明しました。私はテストクラスでこれを証明しました:

System.out.println("User objects equal = " + (user == dao.getUser())); 

これは偽です。私は、同じキーを使用するEntityManagerへのすべての呼び出しが同じオブジェクト参照を返すことを期待していましたが、これが当てはまらないことを知るためには驚いていました。誰もこれにどのような光を当てることができますか?実際には問題ではないので、私のコードをリファクタリングしました(DAOはUserオブジェクトを持っていてはいけません)。

ありがとうございます!

Java 1.6u22、Toplink Essentials 2.0.1、Spring 2.5.6

答えて

5

find()は、永続コンテキストのスコープ内に同じインスタンスを返します。永続コンテキスト(JPA仕様の点でコンテナ管理トランザクションスコープ永続コンテキスト)共有EntityManagerの場合

ライフサイクルは、同じトランザクションから呼び出されたときに同じインスタンスを返しfind()従って、トランザクションにバインドされています。 あなたのケースでは、テストの設定がテストメソッドと同じトランザクションで行われないと思いますので、 find()は異なるインスタンスを生成します。

+1

axtavtが正しい。 EntityManagerが閉じられると、それに関連付けられた永続コンテキストがガベージコレクトされます。 EntityManagerのインスタンスがトランザクションとともにコンテナによって自動的に提供される場合、同じトランザクション(およびEntityManager)がまだ存在する限り、em.find()の呼び出しは常に同じ主キーの同じ物理オブジェクトを返します開いた。より長い寿命を持つEntityManagerが必要な場合は、コンテナ管理のEntityManagerを使用するオプションがありますが、余分な作業が必要になります。 –

+0

あなたの回答に感謝します。 @Beforeと@Afterというアノテートされたメソッドは@Transactionalアノテーションに含まれているため、テストと私のDAOの両方で共有されるトランザクションは1つだけです。 Toplinkログには、単一のトランザクションも表示されます。ですから、テストクラスとDAOの両方で同じEntityManagerを取得してはいけないと思います。 2つのEntityManagersが同じかどうかを調べる方法はありますか? Springが私に与える共有EntityManagerは、実際に呼び出しを委任するプロキシであることが分かります。したがって、わかりやすいチェック方法はありません。 – Conan

+0

@Conan:チェックしたところ、 '@ Before' /' @ After'メソッドは実際に '@ Test'と同じトランザクションで実行されていたので、' em.find() 'は同じインスタンスを返します。おそらく、あなたの問題には別の原因があります。 'TransactionSynchronizationManager.getCurrentTransactionName()'を記録すると、トランザクションIDを確認できます。 – axtavt

0

いいえ、それはありません。とにかくIDENTITYではなくEQUALITYオブジェクトに頼るべきです。 equalsメソッドをオーバーライドします。

関連する問題