web-dev-qa-db-ja.com

SpringのOpenEntityManagerInViewFilterを使用しない理由

SpringのOpenSession/EntityManagerInViewFilterをテーマにした投稿がたくさん書かれていますが、その欠陥について言及しているものは見つかりませんでした。私が理解していることから、@ Transactionalサービスレイヤーを使用する典型的なレイヤードWebアプリケーションアーキテクチャを想定すると、フィルターは次のように機能します。

  1. フィルタはサーブレットリクエストをインターセプトします
  2. フィルタはEntityManagerを開き、現在のスレッドにバインドします
  3. Webコントローラーは
  4. Webコントローラーがサービスを呼び出す
  5. トランザクションインターセプターは新しいトランザクションを開始し、スレッドにバインドされたEntityManagerを取得して、トランザクションにバインドします
  6. サービスが呼び出され、EntityManagerでいくつかの処理を実行してから、
  7. トランザクションインターセプターはEntityManagerをフラッシュしてから、トランザクションをコミットします
  8. Webコントローラーはビューを準備してから、
  9. ビューが構築されます
  10. フィルタはEntityManagerを閉じ、現在のスレッドからバインドを解除します

手順8と9では、スレッドのEntityManagerによってロードされたオブジェクトは引き続き管理されます。したがって、これらの手順で遅延アソシエーションに触れた場合、それらはまだ開いているEntityManagerを使用してデータベースからロードされます。私の理解では、そのようなアクセスごとに、データベースがトランザクションを開く必要があります。 Springのトランザクション管理はこれを認識しないため、私はこれを「暗黙のトランザクション」と呼んでいます。

これには2つの問題があります。

  1. 複数の遅延アソシエーションをロードすると、複数のデータベーストランザクションが発生し、パフォーマンスに影響を与える可能性があります
  2. ルートオブジェクトとその遅延アソシエーションは異なるデータベーストランザクションでロードされるため、データが古くなっている可能性があります(たとえば、ルート1によってロードされたルート、スレッド2によって更新されたルートアソシエーション、スレッド1によってロードされたルートアソシエーション)

一方では、これらの2つの問題は、このフィルターの使用を拒否するのに十分であるように思われます(パフォーマンスの低下、データの不整合)。一方、このソリューションは非常に便利で、数行のコードを書く必要がありません。問題1はそれほど目立たない可能性があり、問題2は純粋な妄想である可能性があります。

どう思いますか?

ありがとう!

37
user186427

あなたが言ったように、OpenSessionInViewフィルターはWebアプリケーションで非常に便利です。あなたが言及した制限について:

1)複数の遅延アソシエーションをロードすると、複数のデータベーストランザクションが発生し、パフォーマンスに影響を与える可能性があります。

はい、DBにアクセスすると、パフォーマンスの問題が発生することがよくあります。理想的には、1回の旅行で必要なすべてのデータをフェッチする必要があります。これにはHibernateのjoin-fetchの使用を検討してください。ただし、DBからのデータのフェッチも遅くなります。私が使用する経験則は、ビューをペイントするたびにデータが必要な場合は、結合フェッチを使用することです。ほとんどの場合、データが必要ない場合は、必要なときにHibernateにレイジーフェッチさせます。スレッドローカルオープンセッションが役立ちます。

2)ルートオブジェクトとそのレイジーアソシエーションは異なるデータベーストランザクションにロードされるため、データが古くなっている可能性があります(たとえば、スレッド1によってロードされたルート、スレッド2によって更新されたルートアソシエーション、スレッド1によってロードされたルートアソシエーション)。

このアプリケーションをJDBCで作成することを想像してみてください。アプリケーションの整合性要件で、ルートとリーフの両方を同じtxnにロードする必要がある場合は、結合フェッチを使用してください。そうでない場合は、よくあることですが、遅延フェッチによって整合性の問題が発生することはありません。

IMHO、OpenSessionInViewのより重要な欠点は、サービスレイヤーをWeb以外のコンテキストで再利用する場合です。あなたの説明から、あなたはその問題を抱えていないようです。

9
Binil Thomas

OpenSessionInViewFilterで発生した主な問題の1つは、AJAXアプリとjavascriptを使用することです。javascriptを使用してグリッドまたは特定のUIコンポーネントをレンダリングしている場合は、遅延読み込みが発生します(フィルタをオンにします);そして例外がスローされます。アプリケーションのUIレンダリングはトスになります。データが表示されない可能性があり、ページは奇妙なjavascript例外をスローし始めます。そのため、処理する追加のjsコードを記述する必要があります。 db例外をユーザーに公開しています(お勧めできません)。

通常のアプリケーションでは、これらの例外をキャプチャして、有効なユーザー例外をスローできます。

4
Varun Mehta

OpenSessionInViewと遅延読み込みに対して私が聞いた主な議論は、トランザクションの過剰とパフォーマンスへの悪影響です。使用要件の低いアプリでの使用は非常に便利ですが、大規模なアプリでは、昔ながらの完全に入​​力されたDTO(データ転送オブジェクト)を使用することをお勧めします。

4
Kaleb Brasee

アプリケーションが多層アーキテクチャである場合(ビューレイヤーが異なるJVMにデプロイされ、サービスレイヤーが異なるVMにデプロイされる)、セッションをオープン状態に保つことは意味がありません。サービス層がアプリ層から独立している場合、OpenSessionViewFilterを使用しないと思います。

1
unds