#author("2021-06-24T05:33:30+00:00","","")
#author("2021-06-24T05:33:35+00:00","","")
[[SpringBoot]]

* Spring Bootにおける DTO, Form, Entityの違い [#r7154a00]

2020-05-18 中村

** 概要 [#se655af1]
Spring Bootのレイヤ間でやりとりされるJava Beans (POJO)の呼び方.

ざっくり言えば以下の通りか.
- DTO: ドメインオブジェクト.サービス・処理毎に最適な形をとる.
- Form: @Viewクラスから渡されるユーザ入力を保持するオブジェクト.@ViewとやりとりするDTOとみなしてもよい
- Entity: DBにミラーリングされるオブジェクト

&attachref();
&attachref(spring_layered_architecture3.png);

PitCoin(拡張版)を例にとって説明してみる.
- 以下のデータを持つアプリと思ってください

** Entity [#me9677a6]
データベースのテーブルをそのままミラーリングしたJavaオブジェクト.

メンバにアノテーションしておくと,CRUDする際にあんじょう変換&検査してくれる.

まとめると
- データベースに保存するものを記述する
- データベースに入れる、取り出す時に利用する

 @Data
 @Entity
 public class User {
     @Id
     String uid;               //ユーザID
 
     @NotEmpty
     String name;              //ユーザ氏名 
 
     @NotEmpty
     String password;          //パスワード
 
     @NotEmpty
     String email;             //Email
 
     boolean admin;            //管理者かどうか
 
     boolean enabled;          //有効かどうか
 
     @Temporal(TemporalType.TIMESTAMP)
     Date enabledAt;           //有効になった日時
 
     @Temporal(TemporalType.TIMESTAMP)
      Date disabledAt;          //凍結された日時
 
     String remark;            //注釈
 }

** Form [#v39a1c09]
Viewから受け取るユーザの入力フォームを保持するJavaオブジェクト.
@Controllerのメソッドの引数(@ModelAttribute または @RequestBody)として受取り,バリデーション(@Validated)される.

一般的にメンバはすべてString.バリデーションのためのアノテーションが施される.
- 入力しないといけない
- メールアドレスの形式にあっているかチェックする、など

入力に特化したDTOとも考えられるが,数値変換する前の数字文字列や,暗号化前のパスワード等,
ユーザの入力そのものを(エラー等に備えて)保持しておくために,FormとDTO(後述)は別で作ったほうが
良いらしい.

まとめると
- ユーザが入力するデータを記述する
- きちんとバリデーション(妥当性の確認)をする
 
 @Data
 public class UserForm {
     /* ユーザID は 最大16文字.英数字,アンダーバー,ハイフンのみ許す */
    @Size(max = 16)
     @Pattern(regexp = "[0-9a-zA-Z_\\-]+")
     private String uid;
 
     /* 名前,パスワードは Null,空文字(""),空白のみでないことを検証*/
     @NotBlank
     private String name;
 
     @NotBlank
     private String password;
     
     /* RFC2822に準拠したEmailアドレスかどうか検証する */
     @Email
     private String email;
 }

** DTO (Data Transfer Object) [#d585ee7c]
様々なEntityやFormから必要なデータを集めて詰め込んで,受け渡ししやすい形にしたオブジェクト.

業務ロジックに応じて作られる.FormもDTOの一種といってよいかもしれないがDTOはフォームに限らない.

以下はDTOの一例

 //ユーザの口座照会用 DTO
 @Data
 public class UserAccountDTO {
    String uid;     //ユーザID
    String name;    //ユーザ氏名
    
    int aid;        //口座番号
    int coin;       //口座残高
 
    List <Record> records; // 取引履歴
 }



まとめると
- 必要なデータの受け渡し(システム内、ユーザに提示)に利用
- 最低限必要なデータを、必要な形で処理する


* なんでこんなに分けてるの? [#v79bd960]
「全部Entityで処理すれば簡単」と思った貴方、私もそう思います。

全てをEntityにした場合、こんな問題が発生します。

+ 情報の肥大化、高負荷
-- 1つのEntityに情報が数百と入っている場合、それの通信、呼び出しに時間がかかる。
-- 加えて、必要な情報が分かりにくい、処理が面倒といった問題にもつながる。
+ 不適切なデータにアクセスできる
-- ContorollerにEntityが行くと、その中のpasswordなど秘匿されるべきデータにもアクセスできる。
-- 何かのバグで公開させる危険性もあり、あらかじめデータを制限することが必要になる。
+ ユーザの入力が面倒
-- Entityしか使わないと、ユーザが必要な情報を全て入力しなければならない。
-- 作成日や、有効かどうかとか、IDとか...
+ 変更に弱い
-- 仮にEntityの要素を増やすとなったとき、関連する全てを変更する必要がある。
-- DTOやFormがあれば、その部分は変更しなくてよく、変更を最小限にとどめられる
-- =>バグの可能性を下げることができる

などなど、意外とよくない点は多い。

とりあえず、以下のことを思いながら開発していくと、だんだんわかってくる
- ユーザが入力するのはform
- データベースに出し入れするのはentity
- クラス間の通信、ユーザに見せるのはdto



* 参考文献 [#lf3ac23e]
-【Java】formとentityとdtoの違いって?【Bean】
-- https://qiita.com/mtanabe/items/c879d233d297eda288d4
-【JavaBeans】BeanとDTOとEntityとVOとFormの違いって何?
-- https://yyyank.blogspot.com/2013/07/javabeansbeandtoentityvoformwhat-is.html

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS