ホームページ  >  記事  >  Java  >  DTO をスキップすると何が起こるか

DTO をスキップすると何が起こるか

WBOY
WBOYオリジナル
2024-07-30 09:46:01646ブラウズ

What can happen if you skip the DTOs

SpringBoot のようなフレームワークで非常に多くのことができるのは素晴らしいことです。

必要なのは JPA エンティティ クラスと単純なリポジトリ インターフェイスだけであり、SpringData は一般的な CRUD データベース操作に必要なものをすべて提供します。

単純な REST コントローラー クラスを作成し、REST API を実行していますよね?

おい、でも DTO を書くのを忘れた!しかし、アプリがなくても機能するのに、実際にはなぜそれが必要なのでしょうか?

確かに一般的な理由がいくつかあります:

  • 階層構造 (例: 六角形のアーキテクチャ、ポートとアダプター): 保守性を高めるために、外部通信コードをコア (ビジネス ロジック) から分離することをお勧めします
  • セキュリティとパフォーマンス: API でデータベース構造をそのまま公開すると、すぐに必要以上のものを公開することになります。悪意のある攻撃者によって悪用されたり、リソース (CPU、メモリ、ネットワーク帯域幅) が無駄になる可能性があります
  • JPA エンティティとは異なり、DTO は不変にすることができ (Java レコードを使用できる)、データ駆動型 (関数型) プログラミング スタイル、優れた単体テスト、より安全な同時実行性などに適しています。

しかし、他にも奇妙なことが起こる可能性があります。私の経験に基づいた奇妙な例を 1 つ紹介します。

この GitHub リポジトリには、DTO なしで動作する単純なアプリケーションが含まれています。ユーザー エンティティがあり、各ユーザーは複数のトランザクションを持つことができます。リポジトリと RestController の間に Service Bean もあり、発生する可能性のあるデータベース アクセス例外をキャッチします。

本番環境に対応したアプリケーションを作成したいので、Hibernate に DDL を生成させたくありません。代わりに、テーブルを作成する schema.sql があります (後で Flyway または Liquibase に切り替える可能性があります)。この簡単な例では、テーブルが空にならないように data.sql も用意しています。

アプリケーションを実行し、http://localhost:8080/users で API エンドポイントを呼び出すと、ユーザーとそのトランザクションを含む予想される JSON が取得されます。

次に、Transaction クラスの // とマークされた 2 行のコードに注目してみましょう。

@JsonIgnore //!!

最初の特徴は、Transaction クラスで @JsonIgnore アノテーションを User 参照に追加する必要があるということです。このアノテーションがないと、JSON シリアル化は無限再帰によりクラッシュします。

次に、誰かがトランザクション エンティティに別のフィールド (説明) を追加するという間違いを犯し、SQL ステートメントの調整を忘れた (または、スキーマ変更が適用されていない環境に対してアプリケーションを実行した) と想像してみましょう。

プライベート文字列の説明;//!!

もちろん、今度は API 呼び出しは失敗します。しかし、エラー処理を見てください。 UserService 内の catch 句が期待どおりに機能しません。代わりに、ログに奇妙なスタック トレースが表示されます。
GlobalExceptionHandler : 予期しないエラー org.springframework.http.converter.HttpMessageNotWritableException: JSON を書き込めませんでした:

私はかつてこの状況を見たことがあり (明らかに、この例よりもはるかに大規模なアプリケーションでした)、SQL 例外がサービスをエスケープした理由と HttpMessageNotWritableException が発生した理由を理解するのにかなりの時間がかかりました。見えますか?

何が起こるかというと、UserService クラスは (UserRepository 経由で) USERS データベース テーブルのみをクエリします。デフォルトの Hibernate 遅延ロードのため、トランザクション エンティティは結果の一部ではありません。 Jackson デシリアライザーが User インスタンスから JSON を作成しようとする場合にのみ、Hibernate に Transaction エンティティをフェッチさせる getTransactions メソッドを呼び出します。

これが、JSON と SQL を組み合わせた奇妙なスタックトレースが得られる理由です。この例外は、処理方法がわからない GlobalExceptionHandler によってキャッチされます。これが、ログ メッセージが「予期しないエラー」となる理由です。

この小さな演習で、アプリケーションの異なるレイヤーを混在させることがいかに危険であるかをより深く理解していただければ幸いです。アプリケーションがまだ小さいうちに、アプリケーションの「晴れた日」のシナリオだけを見ると、一部の開発者は手遅れになるまで間違った行為を続ける可能性があります。

DTO とアプリケーションの他の層の間でフィールドをマッピングする定型コードを記述する必要はありません。 MapStruct が代わりにそれを実行します。

以上がDTO をスキップすると何が起こるかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。