spring.jpa.open-in-view=true
Spring Boot ドキュメントで JPA 構成のプロパティを確認しました。
true
このプロパティがまったく指定されていない場合、デフォルト値になりますか?- これは実際何をするのでしょうか? 良い説明は見つかりませんでした。
SessionFactory
の代わりにを使用する必要がありますかEntityManagerFactory
? そうである場合、代わりに を使用できるようにするにはどうすればよいでしょうかEntityManagerFactory
?
ありがとう!
ベストアンサー1
OSIVアンチパターン
次の図に示すように、OSIV (Open Session in View) は、ビジネス レイヤーに、ビュー レイヤーに必要なすべての関連付けを取得する最適な方法を決定させるのではなく、ビュー レイヤーがプロキシの初期化をトリガーできるように、永続コンテキストを強制的に開いたままにします。
- は基になる の メソッド
OpenSessionInViewFilter
を呼び出し、新しい を取得します。openSession
SessionFactory
Session
- は
Session
、TransactionSynchronizationManager
。 - はオブジェクト参照を
OpenSessionInViewFilter
呼び出し、リクエストはさらに処理されます。doFilter
javax.servlet.FilterChain
- の
DispatcherServlet
が呼び出され、HTTP リクエストが基になる にルーティングされますPostController
。 - は、エンティティのリストを取得するために
PostController
を呼び出します。PostService
Post
- は
PostService
新しいトランザクションを開き、は によって開かれたHibernateTransactionManager
同じトランザクションを再利用します。Session
OpenSessionInViewFilter
- 遅延関連付けを初期化せずにエンティティ
PostDAO
のリストを取得します。Post
- は
PostService
基礎となるトランザクションをコミットしますが、 はSession
外部で開かれたため閉じられません。 - は
DispatcherServlet
UI のレンダリングを開始し、次に遅延関連付けをナビゲートして初期化をトリガーします。 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の警告はデフォルトで有効になっているため、本番システムに影響するずっと前にこの問題を発見できます。