「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > DTO をスキップすると何が起こるか

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

2024 年 8 月 2 日に公開
ブラウズ:871

What can happen if you skip the DTOs

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

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

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

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

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

  • 階層構造 (例: 六角形のアーキテクチャ、ポートとアダプタ): 保守性を高めるために、外部通信コードをコア (ビジネス ロジック) から分離することをお勧めします
  • セキュリティとパフォーマンス: API でデータベース構造をそのまま公開すると、すぐに必要以上のものを公開することになります。悪意のある者によって悪用されたり、リソース (CPU、メモリ、ネットワーク帯域幅) が無駄になる可能性があります
  • DTO は、JPA エンティティとは異なり、不変にすることができ (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 にトランザクション エンティティをフェッチさせる getTransactions メソッドを呼び出します。

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

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

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

リリースステートメント この記事は次の場所に転載されています: https://dev.to/marianvarga/what-c​​an-happen-if-you-skip-the-dtos-aaj?1 侵害がある場合は、削除するために[email protected]に連絡してください。それ
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3