71

長い質問ですが、ご容赦ください。

Web アプリケーションに Spring+JPA を使用しています。私のチームEntityManagerFactoryGenericDAO、. 「アプリケーション管理の永続性」を使用しています。JpaDaosupportEntityManager

a を注入することに対する議論EntityManagerFactoryは、それは重すぎるので必要EntityManagerないということです。EntityManagerまた、Spring は Web リクエストごとに DAO の新しいインスタンスを作成するため (これは疑わしい)、同じインスタンスが 2 つのスレッドで共有されるため、同時実行の問題は発生しません。

EFM を注入することの議論は、ファクトリへのハンドルを持つことは常に良いことです。

どちらが最善のアプローチなのかわからないのですが、誰か教えてもらえますか?

4

4 に答える 4

51

EntityManagerFactory と EntityManager を注入することの長所と短所はすべて、ここの Spring ドキュメントで詳しく説明されていますが、それを改善できるかどうかはわかりません。

そうは言っても、あなたの質問には解決すべき点がいくつかあります。

...Spring は、Web リクエストごとに DAO の新しいインスタンスを作成します...

これは正しくありません。scopeDAO が Spring Bean の場合、Bean 定義の属性を介して別の方法で構成しない限り、それはシングルトンです。すべてのリクエストに対して DAO をインスタンス化するのは気が狂います。

EMF を注入することの議論は、ファクトリへのハンドルを持つことは常に良いことです。

この議論は実際には筋が通っていません。一般的なグッド プラクティスでは、オブジェクトには、そのジョブを実行するために必要な最小限のコラボレーターを注入する必要があります。

于 2009-08-21T07:10:57.023 に答える
28

やっと集めたものを載せます。Spring Reference の「プレーンな JPA に基づく DAO の実装」セクションから:

EntityManagerFactory インスタンスはスレッドセーフですが、EntityManager インスタンスはそうではありません。注入された JPA EntityManager は、JPA 仕様で定義されているように、アプリケーション サーバーの JNDI 環境からフェッチされた EntityManager のように動作します。現在のトランザクション EntityManager がある場合は、すべての呼び出しを委任します。それ以外の場合は、操作ごとに新しく作成された EntityManager にフォールバックし、事実上、その使用がスレッドセーフになります。

これは、JPA 仕様によると EntityManager インスタンスはスレッド セーフではないことを意味しますが、Spring がそれらを処理する場合、それらはスレッド セーフになります。

Spring を使用している場合は、EntityManagerFactory の代わりに EntityManagers を注入することをお勧めします。

于 2009-08-21T11:39:57.057 に答える
9

これについてはすでに十分に説明されていると思いますが、いくつかの点を補強するだけです。

  • Spring によって挿入された場合、DAOはデフォルトでシングルトンです。毎回新しいインスタンスを作成するには、スコープを明示的にプロトタイプに設定する必要があります。

  • @PersistenceContext によって注入されたエンティティ マネージャーは、スレッド セーフです。

そうは言っても、マルチスレッド アプリケーションのシングルトン DAO にはいくつか問題がありました。最終的にDAOをインスタンス化されたBeanにして、問題を解決しました。そのため、ドキュメントには 1 つのことが書かれているかもしれませんが、アプリケーションを徹底的にテストすることをお勧めします。

ファローアップ:

私の問題の一部は、私が使用していると思います

@PersistenceContext(unitName = "unit",
    type = PersistenceContextType.EXTENDED)

PersistenceContextType.EXTENDED を使用する場合は、私の理解が正しければ、手動でトランザクションを閉じる必要があることに注意してください。詳細については、このスレッドを参照してください。

別のフォローアップ:

インスタンス化された DAO を使用することは、非常に悪い考えです。DAO の各インスタンスには独自の永続キャッシュがあり、1 つのキャッシュへの変更は他の DAO Bean によって認識されません。悪いアドバイスで申し訳ありません。

于 2009-08-21T11:43:37.003 に答える
7

DAO に @Repository Spring アノテーションを設定し、EntityManager を Spring で管理し、@PersistenceContext アノテーションで注入することが、すべてをスムーズに機能させる最も便利な方法であることがわかりました。共有 EntityManager と例外変換のスレッド セーフを利用できます。デフォルトでは、たとえばマネージャから複数の DAO を組み合わせると、共有 EntityManager がトランザクションを管理します。最終的には、DAO が貧血になることがわかります。

于 2009-08-21T06:44:24.593 に答える