※学習中のため間違っている箇所があるかもしれません。
はじめに
今回はDTOを実装していきます。
DTOはService
とController
間のデータをやり取りするための重要なオブジェクトです。
しっかりと使用方法を覚えていきましょう
DTOとは
DTO
とはData Transfer Object
の略で、
データを他レイヤーへ転送するためのオブジェクトです。
DTOとEntityについて
DTOとEntityは構造が似ていても責務が異なるため、
明確に使い分ける必要があります。
ここでDTO
の責務について簡単に記載します。
- サービス層とプレゼンテーション層のやり取りを行う
- 外部に公開すべき最小限のデータのみ保持する
- Entityに含まれる機密情報を隠蔽し、レイヤー間の責務分離を実現します
つまり、DTO
は必要最低限のデータを保持し、受け渡す責務を負っています。
一方Entity
は
- ドメインモデルを表現し、DBとの永続化処理の中心
- Rpository層を介して永続化されたデータの取得、更新、削除を行う
となっており、Entity
とDTO
では責務が異なります。
構造が似ている場合があっても、責務と利用範囲が異なるので、明確に理解しておきましょう。
今回は前回のサービス機能をもとにDTO
を作成していきます。
記載しているのは代表的なDTO
で構成は他と同じになっているので、
最小限のDTO
だけ記載させていただきます。
DTOを作成
以下に今回作成した代表的なDTO
を記述します。
他のDTO
でも主な構造は同じなので今回は割愛します。
共通結果返却DTO
ResultDto
共通の結果を返却するためのDTO
です。
主に処理結果やメッセージの返却を行います。
import lombok.Builder;
import lombok.Getter;
/***
* 結果返却DTO
* Service内での処理結果共有で利用する
* Controllerからの返却はしない
*/
@Getter
public class ResultDto {
/***
* 処理結果
*/
private final boolean result;
/***
* メッセージ
* 成功の場合もメッセージを設定
*/
private final String message;
/***
* 初期設定用コンストラクタ
* @param result
* @param message
*/
@Builder
public ResultDto(boolean result, String message){
this.result = result;
this.message = message;
}
}
レスポンス用DTO
GetArticleDetailDto
レスポンス用のDTOです。
DBから取得した値を設定するため、
アノテーションでのバリデーションは行いません。
import java.time.LocalDateTime;
import lombok.Builder;
import lombok.Getter;
/***
* 記事詳細表示用DTO
* 記事の基本的な情報を保持する
*/
@Getter
public class GetArticleDetailDto {
/***
* タイトル
*/
private final String title;
/***
* 内容
*/
private final String content;
/***
* 表示フラグ
*/
private final boolean releaseFlg;
/***
* 作成日
*/
private final LocalDateTime createdAt;
/***
* 更新日
*/
private final LocalDateTime updatedAt;
/***
* 初期設定用コンストラクタ
* @param title
* @param content
* @param releaseFlg
* @param createdAt
* @param updatedAt
*/
@Builder
public GetArticleDetailDto(String title, String content, boolean releaseFlg
, LocalDateTime createdAt, LocalDateTime updatedAt){
this.title = title;
this.content = content;
this.releaseFlg = releaseFlg;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
}
}
リクエスト用DTO
InsertArticleDetailDto
リクエスト用のDTOです
受け取った情報をテーブルへ保存します。
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Builder;
import lombok.Getter;
/***
* 記事投稿用DTO
* 記事投稿時に必要なデータを保持する
*/
@Getter
public class InsertArticleDetailDto {
/***
* ユーザーID
*/
@Min(0)
private final int userId;
/***
* タイトル
*/
@NotBlank
@Size(max=50)
private final String title;
/***
* 内容(本文)
*/
@NotBlank
@Size(max=255)
private final String content;
/***
* 公開フラグ
*/
private final boolean releaseFlg;
/***
* 削除フラグ
*/
private final boolean deleteFlg;
/***
* 初期設定用コンストラクタ
* @param userId
* @param title
* @param content
* @param releaseFlg
* @param deleteFlg
*/
@Builder
public InsertArticleDetailDto(int userId, String title, String content, boolean releaseFlg, boolean deleteFlg){
this.userId = userId;
this.title = title;
this.content = content;
this.releaseFlg = releaseFlg;
this.deleteFlg = deleteFlg;
}
}
削除用DTO
記事削除用のDTOです。
削除フラグを更新する際に使用します。
UpdateUserDeleteFlgDto
import lombok.Builder;
import lombok.Getter;
/***
* ユーザー削除用DTO
* 削除フラグを保持する
*/
@Getter
public class UpdateUserDeleteFlgDto {
/***
* 削除フラグ
*/
private final boolean deleteFlg;
/***
* 初期設定用コンストラクタ
* @param deleteFlg
*/
@Builder
public UpdateUserDeleteFlgDto(boolean deleteFlg){
this.deleteFlg = deleteFlg;
}
}
バリデーションに関して
DTO
はデータの受け渡し用クラスです。
そのためバリデーションは基本的なものだけを使用し、
詳細な処理はService
層で行う予定です。
基本的にバリデーションはEntity
ではなくDTO
やService
で行うべきだと考えています。
アノテーションの説明
@Builder
@Builder
をコンストラクタまたはメソッドに付与することで、
以下のように直感的な形式でインスタンス生成ができるようになります。
InsertArticleDetailDto.builder()
.userId(ユーザーID)
.title(タイトル)
.content(内容)
.releaseFlg(false)
.deleteFlg(false)
.build();
また、今回は使用していませんが、フィールドにList
やSet
などコレクション型を使用している場合
@Singular
を付与することにより要素を1件ずつ追加する形式のビルダーメソッドが生成されます。
public class User {
String name;
String email;
@Singular("content")
List<String> contents;
}
public class Test {
User user = User.builder()
.name("モス・バーガー")
.email("MosLike@gmail.com")
.content("コンテンツ1")
.content("コンテンツ2");
}
このように記述することで、引数の順序を気にせず読みやすくなります。
フィールドの増減があってもコードの修正は最小限で済むので
拡張性、保守性の高い設計が可能です。
まとめ
今回はDTO
の解説をしました。
DTO
とEntity
の違いを明確にして、有効に使用できるようにしていきましょう。
次回以降
-
Service
,Controller
-
React
連携
今回の記事が少しでもspring boot初学者の助けになれば幸いです。
前:Spring Boot + Reactで記事投稿アプリを作成予定|Flyway入門:DBマイグレーションの基礎からテーブル作成・データ挿入まで解説してみた