2012-06-12 17 views
13

私はEclipseLink 2.3.0を使用しています。JPA/EclipseLink:EntityManager.getTransaction()は新しいトランザクションを作成するか、アクティブなトランザクションを返しますか?

EntityManager em = /* get an entity manager */; 
em.getTransaction().begin(); 
// make some changes 
em.getTransaction().commit(); 

変更がデータベースに永続化されていなかった、とのためにこれを見た:私は、私は(それゆえ、コンテナ、無JTAの外で)次のようになり、ユニットテストから呼び出しています方法を持っていますEntityManager.getTransaction()が両方の呼び出しで同じEntityTransactionではなく新しいEntityTransactionを実際に返していることに気付きました。その効果は、最初の呼び出しが新しいトランザクションを作成して開始し、2番目の呼び出しが別のトランザクションを作成し、それをコミットすることです。最初のトランザクションは決してコミットされなかったので、変更は保存されません。

これらのログメッセージが生じた
log.info(em.getTransaction().toString()); 
log.info(em.getTransaction().toString()); 

INFO: org.ecl[email protected]1e34f445 
INFO: org.ecl[email protected]706a4d1a 

IDの2つの異なるインスタンスがあることを検証する二つの異なるオブジェクト我々はこのように、これを確認しました。コードをこれに変更する:

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

ありがとうございました。

答えて

1

JPA仕様(7.5.4項参照)には、トランザクションを開始およびコミットするためのgetTransaction()の使用を示す明示的な例があります。だからあなたのコードはうまくいくはずです。

あなたのテストでは、2つの異なるオブジェクトが得られることが示されていますが、同じトランザクションが使用されているわけではありません。たぶん、返されるオブジェクトは、単一の実際のトランザクションオブジェクトに対するちょっとしたプロキシです。

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

+1

多分私が投稿したコードはうまくいかなかったはずです。私は明確にするために質問に編集しました。 –

+0

私はそれを理解しています。 JPA仕様には、em.getTransaction()を使用してトランザクションを開始してコミットするコードサンプルが含まれているので、私はそれが*うまくいくはずです。したがって、私が言ったように、beginとcommitの間のコードがすでにトランザクションをコミットまたはロールバックしていない限り、EclipseLinkのバグでなければなりません。私の答えはあなたの問題に対する解決策ではなく、コードが機能するはずであるという確認です。私はEclipseLinkにバグを提出することをお勧めします。 –

5

getTransaction()を使用するとJPAとEclipseLinkで動作します(これは私たち自身のテストの仕組みです)。

私は他の何か非常に奇妙なことをしていると思います。

あなたはSpringなどのレイヤを使用していますか? テスト用にcodeとpersistence.xml全体を含めてください。 persistence.xmlでJTAを使用していないことを確認してください。

+0

getTransaction()は、JTAエンティティ・マネージャで呼び出された場合、IllegalStateExceptionをスローする必要があります。 –

+0

春はなく、JTAはありません。これは、コンテナの外部でJUnitテストから呼び出されています。 "いくつかの変更を加える"のコードは4行で、新しいオブジェクトを作成し、整数値を設定してマージしてフラッシュします。私は分を取ると蒸留された例を作ります。おそらく、これはEclipseLinkのバグです。 –

0

persist before commit:を試しましたか?

Employee employee = new Employee("Samuel", "Joseph", "Wurzelbacher"); 
    em.getTransaction().begin(); 
    em.persist(employee); 
    em.getTransaction().commit(); 
関連する問題