SpringのOpenSession/EntityManagerInViewFilterをテーマにした投稿がたくさん書かれていますが、その欠陥について言及しているものは見つかりませんでした。私が理解していることから、@ Transactionalサービスレイヤーを使用する典型的なレイヤードWebアプリケーションアーキテクチャを想定すると、フィルターは次のように機能します。
手順8と9では、スレッドのEntityManagerによってロードされたオブジェクトは引き続き管理されます。したがって、これらの手順で遅延アソシエーションに触れた場合、それらはまだ開いているEntityManagerを使用してデータベースからロードされます。私の理解では、そのようなアクセスごとに、データベースがトランザクションを開く必要があります。 Springのトランザクション管理はこれを認識しないため、私はこれを「暗黙のトランザクション」と呼んでいます。
これには2つの問題があります。
一方では、これらの2つの問題は、このフィルターの使用を拒否するのに十分であるように思われます(パフォーマンスの低下、データの不整合)。一方、このソリューションは非常に便利で、数行のコードを書く必要がありません。問題1はそれほど目立たない可能性があり、問題2は純粋な妄想である可能性があります。
どう思いますか?
ありがとう!
あなたが言ったように、OpenSessionInViewフィルターはWebアプリケーションで非常に便利です。あなたが言及した制限について:
1)複数の遅延アソシエーションをロードすると、複数のデータベーストランザクションが発生し、パフォーマンスに影響を与える可能性があります。
はい、DBにアクセスすると、パフォーマンスの問題が発生することがよくあります。理想的には、1回の旅行で必要なすべてのデータをフェッチする必要があります。これにはHibernateのjoin-fetchの使用を検討してください。ただし、DBからのデータのフェッチも遅くなります。私が使用する経験則は、ビューをペイントするたびにデータが必要な場合は、結合フェッチを使用することです。ほとんどの場合、データが必要ない場合は、必要なときにHibernateにレイジーフェッチさせます。スレッドローカルオープンセッションが役立ちます。
2)ルートオブジェクトとそのレイジーアソシエーションは異なるデータベーストランザクションにロードされるため、データが古くなっている可能性があります(たとえば、スレッド1によってロードされたルート、スレッド2によって更新されたルートアソシエーション、スレッド1によってロードされたルートアソシエーション)。
このアプリケーションをJDBCで作成することを想像してみてください。アプリケーションの整合性要件で、ルートとリーフの両方を同じtxnにロードする必要がある場合は、結合フェッチを使用してください。そうでない場合は、よくあることですが、遅延フェッチによって整合性の問題が発生することはありません。
IMHO、OpenSessionInViewのより重要な欠点は、サービスレイヤーをWeb以外のコンテキストで再利用する場合です。あなたの説明から、あなたはその問題を抱えていないようです。
OpenSessionInViewFilterで発生した主な問題の1つは、AJAXアプリとjavascriptを使用することです。javascriptを使用してグリッドまたは特定のUIコンポーネントをレンダリングしている場合は、遅延読み込みが発生します(フィルタをオンにします);そして例外がスローされます。アプリケーションのUIレンダリングはトスになります。データが表示されない可能性があり、ページは奇妙なjavascript例外をスローし始めます。そのため、処理する追加のjsコードを記述する必要があります。 db例外をユーザーに公開しています(お勧めできません)。
通常のアプリケーションでは、これらの例外をキャプチャして、有効なユーザー例外をスローできます。
OpenSessionInViewと遅延読み込みに対して私が聞いた主な議論は、トランザクションの過剰とパフォーマンスへの悪影響です。使用要件の低いアプリでの使用は非常に便利ですが、大規模なアプリでは、昔ながらの完全に入力されたDTO(データ転送オブジェクト)を使用することをお勧めします。
アプリケーションが多層アーキテクチャである場合(ビューレイヤーが異なるJVMにデプロイされ、サービスレイヤーが異なるVMにデプロイされる)、セッションをオープン状態に保つことは意味がありません。サービス層がアプリ層から独立している場合、OpenSessionViewFilterを使用しないと思います。