長い質問をお願いします。
WebアプリケーションにSpring + JPAを使用しています。私のチームは、EntityManagerFactory
(APPFUSEが提供する行にあるGenericsに基づくDAO。何らかの理由でGenericDAO
を使用しません)にJpaDaosupport
を注入することについて議論しています。 EntityManager
。 「アプリケーション管理の永続性」を使用しています。
EntityManagerFactory
の挿入に対する引数は、その重すぎるため必要ではないということです。EntityManager
は必要なことを行います。また、SpringはすべてのWeb要求に対してDAOの新しいインスタンスを作成するため(これは疑わしい)、同じEntityManager
インスタンスが2つのスレッドで共有されるため、同時実行の問題は発生しません。
EFMを注入するための引数は、ファクトリーへのハンドルを持つことは常に良いことであるということです。
どちらが最善のアプローチかわからないのですが、誰かに教えてください
EntityManagerFactoryとEntityManagerを注入することの長所と短所はすべてSpringのドキュメントで説明されています here 、これを改善できるかどうかはわかりません。
そうは言っても、あなたの質問には解決すべき点がいくつかあります。
... Springは、WebリクエストごとにDAOの新しいインスタンスを作成します...
これは正しくありません。 DAOがSpring Beanである場合、Bean定義のscope
属性を使用して別の方法で構成しない限り、それはシングルトンです。リクエストごとにDAOをインスタンス化するのはおかしいでしょう。
EMFを注入するための引数は、ファクトリーへのハンドルを持つことは常に良いことであるということです。
この議論は実際に水を保持しません。一般的なグッドプラクティスでは、オブジェクトには、ジョブを実行するために必要な最小限の共同作業者を注入する必要があるとされています。
私は最終的に集めたものを置いています。 Spring Referenceの「 プレーンJPAに基づいたDAOの実装 」セクションから:
EntityManagerFactoryインスタンスはスレッドセーフですが、EntityManagerインスタンスはそうではありません。注入されたJPA EntityManagerは、JPA仕様で定義されているように、アプリケーションサーバーのJNDI環境からフェッチされたEntityManagerのように動作します。存在する場合、現在のトランザクションEntityManagerにすべての呼び出しを委任します。それ以外の場合は、操作ごとに新しく作成されたEntityManagerにフォールバックし、その使用を事実上スレッドセーフにします。
つまり、JPA仕様では、EntityManagerインスタンスはスレッドセーフではありませんが、Springがそれらを処理する場合、スレッドセーフになります。
Springを使用している場合は、EntityManagerFactoryの代わりにEntityManagersを注入することをお勧めします。
これはすでに十分にカバーされていると思いますが、いくつかの点を補強するためです。
DAOは、Springによって注入された場合、デフォルトではシングルトンです。毎回新しいインスタンスを作成するには、スコープをプロトタイプに明示的に設定する必要があります。
@PersistenceContextによって挿入されたエンティティマネージャーはスレッドセーフです。
そうは言っても、マルチスレッドアプリケーションのシングルトンDAOにはいくつかの問題がありました。 結局、DAOをインスタンス化されたBeanにして、問題を解決しました。 そのため、ドキュメントには1つのことが書かれていますが、おそらくアプリケーションを徹底的にテストする必要があります。
フォローアップ:
私の問題の一部は私が使用していると思います
@PersistenceContext(unitName = "unit",
type = PersistenceContextType.EXTENDED)
PersistenceContextType.EXTENDEDを使用する場合、正しく理解できた場合は手動でトランザクションを閉じる必要があることに注意してください。詳細については、 this threadを参照してください。
別のフォローアップ:
インスタンス化されたDAOを使用することは非常に悪い考えです。 DAOの各インスタンスには独自の永続キャッシュがあり、1つのキャッシュへの変更は他のDAO Beanによって認識されません。悪いアドバイスでごめんなさい。
DAOに@Repository Springアノテーションを設定し、Springによって管理され@PersistenceContextアノテーションによって挿入されたEntityManagerを持つことは、すべてを流workingに機能させる最も便利な方法であることがわかりました。共有されたEntityManagerと例外変換のスレッドセーフの恩恵を受けます。デフォルトでは、たとえば、マネージャーからの複数のDAOを組み合わせた場合、共有EntityManagerがトランザクションを管理します。最終的に、DAOが貧血になることがわかります。