1. ホーム
  2. java

Spring MVCのコントローラを@Transactionalにしない方がいい理由とは?

2023-07-13 21:31:20

疑問点

このトピックに関する質問はすでにいくつかありますが、Spring MVCコントローラを作るべきではない理由を説明するための議論を提供してくれる回答はまったくありません。 Transactional . 見てください。

では、なぜ?

  • はあるのでしょうか? 乗り越えられない 技術的な問題はありますか?
  • アーキテクチャ上の問題はありますか?
  • パフォーマンス/デッドロック/同時実行の問題はありますか?
  • 複数の個別のトランザクションが必要な場合がありますか?もしそうなら、どのようなユースケースがありますか?(サーバーへの呼び出しが完全に成功するか、完全に失敗するかのどちらかであるという単純化されたデザインが好きです。それは非常に安定した動作に聞こえます)

背景 私は数年前、C#/NHibernate/Spring.Net で実装された非常に大規模な ERP ソフトウェアのチームで働いていました。サーバーへのラウンド トリップは、まさにそのように実装されていました。トランザクションは、任意のコントローラ ロジックに入る前に開かれ、コントローラを終了した後にコミットまたはロールバックされました。トランザクションはフレームワークで管理され、誰もそれを気にする必要はありませんでした。 安定していて、シンプルで、数人のアーキテクトだけがトランザクションの問題を気にする必要があり、残りのチームは機能を実装するだけでよかったのです。

私の観点では、これは私がこれまで見た中で最高のデザインです。Spring MVC で同じ設計を再現しようとすると、遅延ロードとトランザクションの問題で悪夢を見ることになり、毎回同じ答えが返ってきました。

あなたの設立された回答を事前にありがとうございました

どのように解決するのですか?

TLDR : これは、アプリケーションのサービス層だけが、データベース/ビジネストランザクションの範囲を特定するために必要なロジックを持つためです。設計上、コントローラーと永続化層はトランザクションのスコープを知ることはできませんし、知るべきではありません。

コントローラは @Transactional にすることもできますが、実際にはサービス層のみをトランザクションにすることが一般的な推奨事項です(永続化層もトランザクションにすべきではありません)。

この理由は、技術的な実現可能性ではなく、関心事の分離です。コントローラの責任は、パラメータリクエストを取得し、1つまたは複数のサービスメソッドを呼び出し、結果をレスポンスにまとめ、クライアントに送り返すことです。

つまり、コントローラはリクエスト実行の調整役と、ドメインデータをクライアントが消費できる形式(DTOなど)に変換する機能を持つのです。

ビジネスロジックはサービス層に存在し、永続化層はデータベースとの間でデータを取得/保存するだけです。

口座振替では、他方が入金されている場合のみ口座が引き落とされるなど、ビジネスロジックを含むサービス層のみが銀行口座振替のトランザクションの範囲を実際に知ることができます。

永続化レイヤーはどのようなトランザクションであるかを知ることができません、例えば、メソッド customerDao.saveAddress . このメソッドは常に別のトランザクションで実行されるべきなのでしょうか。時にはそれは別のトランザクションで実行されるべきですし、時には saveCustomer が動作した場合のみデータを保存する、などです。

同じことがコントローラにも当てはまります。 saveCustomersaveErrorMessages が同じトランザクションに入るのですか?あなたは、顧客を保存し、それが失敗した場合、いくつかのエラーメッセージを保存し、データベースに保存したいエラーメッセージを含むすべてをロールバックするのではなく、適切なエラーメッセージをクライアントに返すようにしたいと思うかもしれません。

非トランザクションコントローラでは、サービス層から返されるメソッドは、セッションが終了しているため、切り離されたエンティティを返します。これは正常な動作で、解決策としては OpenSessionInView を使用するか、コントローラが必要とする結果を熱心に取得するクエリを実行することです。

とはいえ、コントローラをトランザクションにすることは罪ではありません。