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

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

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

  • trueこのプロパティがまったく指定されていない場合、デフォルト値になりますか?
  • これは実際何をするのでしょうか? 良い説明は見つかりませんでした。
  • SessionFactoryの代わりにを使用する必要がありますかEntityManagerFactory? そうである場合、代わりに を使用できるようにするにはどうすればよいでしょうかEntityManagerFactory?

ありがとう!

ベストアンサー1

OSIVアンチパターン

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

OSIVアンチパターン

  • は基になる の メソッドOpenSessionInViewFilterを呼び出し、新しい を取得します。openSessionSessionFactorySession
  • SessionTransactionSynchronizationManager
  • はオブジェクト参照をOpenSessionInViewFilter呼び出し、リクエストはさらに処理されます。doFilterjavax.servlet.FilterChain
  • DispatcherServletが呼び出され、HTTP リクエストが基になる にルーティングされますPostController
  • は、エンティティのリストを取得するためにPostControllerを呼び出します。PostServicePost
  • PostService新しいトランザクションを開き、は によって開かれたHibernateTransactionManager同じトランザクションを再利用します。SessionOpenSessionInViewFilter
  • 遅延関連付けを初期化せずにエンティティPostDAOのリストを取得します。Post
  • PostService基礎となるトランザクションをコミットしますが、 はSession外部で開かれたため閉じられません。
  • DispatcherServletUI のレンダリングを開始し、次に遅延関連付けをナビゲートして初期化をトリガーします。
  • OpenSessionInViewFilterは を閉じることができ、Session基礎となるデータベース接続も解放されます。

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

サービス レイヤーはデータベース トランザクションを開始および終了しますが、その後は明示的なトランザクションは実行されません。このため、UI レンダリング フェーズから発行されるすべての追加ステートメントは、自動コミット モードで実行されます。自動コミットでは、各トランザクションが最後にコミットを発行し、ディスクへのトランザクション ログのフラッシュをトリガーするため、データベース サーバーに負荷がかかります。最適化の 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以降、Spring Bootの問題OSIVの警告はデフォルトで有効になっているため、本番システムに影響するずっと前にこの問題を発見できます。

おすすめ記事