Spring Bootのこのspring.jpa.open-in-view = trueプロパティとは何ですか?


121

spring.jpa.open-in-view=trueSpring BootのドキュメントでJPA構成のプロパティを見ました。

  • true、それがすべてで提供されていない場合、このプロパティのデフォルト値は?;
  • これは実際に何をしますか?私はそれについての良い説明を見つけることができませんでした。
  • SessionFactory代わりに使用させEntityManagerFactoryますか?はいの場合、EntityManagerFactory代わりに使用できるようにするにはどうすればよいですか?

ありがとう!

回答:


52

このプロパティは、現在のスレッドOpenEntityManagerInViewInterceptorにを登録するEntityManagerを登録するためEntityManager、Webリクエストが完了するまで同じです。Hibernate SessionFactoryなどとは関係ありません。


現時点では、Webリクエストが完了するまでEntityManagerを制御するためのフィルターOpenEntityManagerInViewFilterがあります。「OpenEntityManagerInViewInterceptor」を意味するこのインターセプターは「OpenEntityManagerInViewFilter」と同じですか?それらの違いは何ですか?では、Spring Bootのサーブレットコンテキストにこのフィルターを追加する必要はありませんか?
カルロスアルベルト

1
インターセプターが機能するのは、DispatcherServletをSpringで使用する場合のみです(インターセプターはSpringメカニズムであるため)。フィルターは、構成されたすべてのサーブレットにマップできます(アプリケーションの1つでFacesServletに使用します)。したがって、DispatcherServletのみを使用する場合は、プロパティを追加してフィルターを削除できます。それ以外の場合はフィルターを使用します。
dunni 2015年

298

OSIVアンチパターン

図に示すように、ビジネスレイヤーにビューレイヤーで必要なすべての関連付けを取得するのに最適な方法を決定させる代わりに、OSIV(ビューでセッションを開く)は、ビューレイヤーがプロキシの初期化をトリガーできるように、永続コンテキストを強制的に開いたままにします。次の図によって。

ここに画像の説明を入力してください

  • OpenSessionInViewFilter呼び出してopenSession根底にあるの方法SessionFactoryと新しいを取得Session
  • SessionにバインドされていますTransactionSynchronizationManager
  • OpenSessionInViewFilter呼び出しdoFilterjavax.servlet.FilterChainオブジェクト参照を、要求がさらに処理されます
  • DispatcherServlet根本的にHTTPリクエストと呼ばれ、ルートされますPostController
  • はをPostController呼び出してエンティティのPostServiceリストを取得しますPost
  • PostService新しいトランザクションを開き、HibernateTransactionManager同じ再利用Sessionによって開かれたものOpenSessionInViewFilter
  • は、遅延関連付けを初期化せずPostDAOPostエンティティのリストをフェッチします。
  • PostService基礎となるトランザクションをコミットしますが、Sessionそれは外部に開かれたために閉鎖されていません。
  • DispatcherServlet今度は、遅延関連付けをナビゲートし、その初期化をトリガー、UIを、レンダリングを開始。
  • OpenSessionInViewFilterを閉じることができSession、基になるデータベース接続も解放されます。

一見すると、これはひどいことのようには見えないかもしれませんが、データベースの観点から見ると、一連の欠陥がより明白になります。

サービス層はデータベーストランザクションを開いたり閉じたりしますが、その後は明示的なトランザクションは発生しません。このため、UIレンダリングフェーズから発行される追加のステートメントはすべて、自動コミットモードで実行されます。各ステートメントはトランザクションログをディスクにフラッシュする必要があるため、自動コミットはデータベースサーバーに負荷をかけ、データベース側で大量のI / Oトラフィックを引き起こします。最適化の1つはConnection、データベースサーバーがトランザクションログへの書き込みを回避できるように、読み取り専用としてマークすることです。

ステートメントはサービスレイヤーとUIレンダリングプロセスの両方で生成されるため、問題の分離はもうありません。生成されるステートメントの数アサートする統合テストを作成するには、アプリケーションをWebコンテナーにデプロイしながら、すべてのレイヤー(Web、サービス、DAO)を通過する必要があります。インメモリデータベース(HSQLDBなど)と軽量Webサーバー(Jettyなど)を使用している場合でも、これらの統合テストは、レイヤーが分離されてバックエンド統合テストがデータベースを使用する場合よりも実行が遅くなります。フロントエンド統合テストは、サービス層を完全に模倣していました。

UIレイヤーは、N + 1クエリの問題を引き起こす可能性のある関連付けのナビゲートに制限されています。Hibernateは@BatchSize関連付けをバッチでフェッチFetchMode.SUBSELECTし、このシナリオに対処するために提供していますが、アノテーションはデフォルトのフェッチプランに影響を与えるため、すべてのビジネスユースケースに適用されます。このため、現在のユースケースのデータフェッチ要件に合わせて調整できるため、データアクセス層クエリの方がはるかに適しています。

最後に重要なことですが、データベース接続はUIレンダリングフェーズ全体を通じて保持されます。これにより、接続リース時間が増加し、データベース接続プールの輻輳が原因でトランザクション全体のスループットが制限されます。接続が保持されるほど、他の同時要求はプールから接続を取得するために待機することになります。

Spring BootおよびOSIV

残念ながら、OSIV(Open Session in View)はSpring Bootではデフォルトで有効になっており、パフォーマンスとスケーラビリティの観点から、 OSIVは本当に悪い考えです。

したがって、application.properties構成ファイルに次のエントリがあることを確認してください。

spring.jpa.open-in-view=false

これによりOSIVが無効になりLazyInitializationException、正しい方法で処理できるようになります。

バージョン2.0以降、OSがデフォルトで有効になっている場合、Spring Boot は警告を発行するため、本番システムに影響するずっと前にこの問題を発見できます。

OSIVの詳細については、こちらの記事をご覧ください。


14
最近ログに記録されている警告があります。
Vlad Mihalcea

これは一般的なSpringに適用されますか、Spring Bootのみに適用されますか?これは、プロパティを設定する代わりに、@ Configuration-annotatedクラスを介して無効にできますか?
ゴードン

2
これは、Spring Bootにのみ適用されます。標準のSpringでは、使用するBeanを明示的に選択するか、OSIVなどのWebフィルターが必要かどうかを明示的に選択します。アノテーションで無効にできるかどうかはわかりません。構成設定しか知りません。
Vlad Mihalcea

それはアンチパターンではありません。それはパフォーマンスに影響を及ぼし、時には否定的で、多くの場合はかなり中立的で、多くの場合は肯定的な方法で影響します。実際に遅延リレーションを始めたい場合は、すべてのケースでクエリを実行する必要はありません。必要に応じて、open-in-viewを使用して回避できます。
ymajoros

5
ウィキペディアによると、「アンチパターンは、通常は効果がなく、逆効果のリスクが高い、繰り返し発生する問題に対する一般的な対応です。」それがまさにOpen Session in Viewです。
Vlad Mihalcea
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.