カテゴリ: Spring 更新日: 2025/11/08

SpringのDTOとプロジェクション最適化を完全ガイド!インターフェイスとクラスベースの違いとは?

DTO/プロジェクション最適化:インターフェイス/クラスベースの返却
DTO/プロジェクション最適化:インターフェイス/クラスベースの返却

先生と生徒の会話形式で理解しよう

生徒

「Springでデータを取得するときに、エンティティじゃなくてDTOを返す方法ってあるんですか?」

先生

「はい、Spring Data JPAではDTOを使ったプロジェクションが可能で、パフォーマンス最適化にもつながります。」

生徒

「クラスで受け取る方法と、インターフェイスで受け取る方法があるって聞いたんですが、違いがよく分かりません…」

先生

「それじゃあ、DTOとプロジェクションの基本から、クラスベース・インターフェイスベースの違い、最適な使い分けまで一緒に学んでいきましょう。」

1. DTOとプロジェクションとは?Springにおける意味

1. DTOとプロジェクションとは?Springにおける意味
1. DTOとプロジェクションとは?Springにおける意味

DTO(Data Transfer Object)は、クライアントに返却するデータを最適化・整形するためのオブジェクトです。Springではエンティティをそのまま返すよりも、DTOを使って必要なデータだけを選んで返す方が安全でパフォーマンスも良くなります。

プロジェクションとは、エンティティの中から必要な項目だけを取り出して別の形式で返す仕組みです。Spring Data JPAではこのプロジェクションを活用してDTOにデータをマッピングすることができます。

2. クラスベースのDTOでデータを返す方法

2. クラスベースのDTOでデータを返す方法
2. クラスベースのDTOでデータを返す方法

まずは、コンストラクタを持つDTOクラスを定義し、JPQLでそのクラスにデータを詰める方法です。


public class UserDto {
    private String name;
    private String email;

    public UserDto(String name, String email) {
        this.name = name;
        this.email = email;
    }

    // getter省略
}

このDTOに対して、以下のようなリポジトリメソッドを用意します。


@Query("SELECT new com.example.demo.dto.UserDto(u.name, u.email) FROM User u")
List<UserDto> findAllUserDtos();

この方法の特徴は、型安全で補完も効くこと、バリデーションを追加しやすいことです。

3. インターフェイスベースのプロジェクションとは?

3. インターフェイスベースのプロジェクションとは?
3. インターフェイスベースのプロジェクションとは?

Spring Data JPAでは、DTOクラスを作らずとも、インターフェイスに対してデータをマッピングすることができます。これはインターフェイスベースのプロジェクションと呼ばれます。


public interface UserNameOnly {
    String getName();
}

このように定義したインターフェイスに対し、リポジトリでは以下のように記述します。


List<UserNameOnly> findBy();

フィールド名に一致するゲッターがあれば、自動的にプロジェクションしてくれる仕組みです。クエリを明示しなくても使えるのが便利ですが、動的な整形には不向きです。

4. ネストしたプロジェクションも可能

4. ネストしたプロジェクションも可能
4. ネストしたプロジェクションも可能

インターフェイスプロジェクションでは、関連エンティティを含めたネスト構造も対応できます。例えば、Userの中に所属する部署名も表示したい場合、以下のようにします。


public interface UserWithDepartment {
    String getName();
    DepartmentInfo getDepartment();

    interface DepartmentInfo {
        String getName();
    }
}

このようにネストしたインターフェイスを定義することで、JOIN FETCHのような処理を省略して柔軟にデータを取得することが可能です。

5. SpringでDTO/プロジェクションを使うメリット

5. SpringでDTO/プロジェクションを使うメリット
5. SpringでDTO/プロジェクションを使うメリット

DTOやプロジェクションを使うことには以下のようなメリットがあります。

  • エンティティの情報を隠蔽できる(セキュリティ・構造の独立)
  • APIレスポンスの整形がしやすい(REST API設計)
  • データ転送量が減り、パフォーマンスが向上
  • クライアントにとって分かりやすい構造で返せる

6. インターフェイスとクラスベースの使い分け方

6. インターフェイスとクラスベースの使い分け方
6. インターフェイスとクラスベースの使い分け方

では、どちらのプロジェクションを選べばよいのでしょうか?以下のように使い分けるのが基本です。

  • インターフェイスベース:簡単な取得だけで十分、クエリ定義を省略したい場合
  • クラスベース:複雑な処理・整形・バリデーションが必要な場合

特にフロントエンド向けAPIでは、JSON構造に応じてクラスベースのDTOで制御する方が管理しやすく、保守性にも優れます。

7. @ValueやSpELによるフィールド整形も可能

7. @ValueやSpELによるフィールド整形も可能
7. @ValueやSpELによるフィールド整形も可能

DTOに直接クエリ結果をマッピングするだけでなく、文字列を整形したり、フィールドを加工したいときは、Spring Expression Language(SpEL)を使う方法もあります。


@Query("SELECT new com.example.dto.UserDto(CONCAT(u.name, 'さん'), u.email) FROM User u")
List<UserDto> findDecoratedUsers();

このようにCONCATSUBSTRING関数を使って、取得時に装飾された値を返すこともできます。

8. Projectionの注意点と落とし穴

8. Projectionの注意点と落とし穴
8. Projectionの注意点と落とし穴

インターフェイスベースのプロジェクションは、フィールド名に厳密に依存するため、エンティティ側のプロパティ名が変わると動作しなくなるリスクがあります。また、JOINが必要な場合や複雑な整形処理には不向きです。

クラスベースDTOは柔軟ですが、コンストラクタの定義やクエリ記述が必要になるため、開発コストがやや高くなります。シーンに応じた使い分けが成功のカギです。

Springの学習を効率化したい方へ

この記事の内容をもっと深く知るには、以下の入門書が最適です。

Spring Framework超入門をAmazonで見る
カテゴリの一覧へ
新着記事
New1
Java
Javaのラムダ式で注意したい変数キャプチャの落とし穴とは?代入と変数名のベストプラクティス解説
更新記事
New2
Spring
Springの@GetMappingアノテーションの使い方を徹底解説!初心者でもわかるSpring Boot入門
更新記事
New3
Spring
SpringDataJPAのJPAクエリメソッド「EndingWith」の使い方を完全ガイド!初心者向け解説
更新記事
New4
Spring
SpringDataJPAのJPAクエリメソッド「StartingWith」の使い方を完全ガイド!初心者向け解説
更新記事
人気記事
No.1
Java&Spring記事人気No1
Spring
Spring BootとJavaの互換性一覧!3.5/3.4/3.3はJava 21・17に対応してる?
No.2
Java&Spring記事人気No2
Java
JavaのBooleanクラスの使い方を完全ガイド!初心者でもわかる真偽値の操作
No.3
Java&Spring記事人気No3
JSP
JSPの基本タグ一覧と使い方まとめ!実務で使えるタグを紹介
No.4
Java&Spring記事人気No4
Java
JavaのIOExceptionクラス徹底解説!初心者向けファイル入出力エラー対策ガイド
No.5
Java&Spring記事人気No5
Spring
SpringのBindingResultを完全ガイド!初心者でもわかる入力チェックとエラー処理
No.6
Java&Spring記事人気No6
JSP
JSPでif文・for文を使う方法!初心者でもわかるJavaとの違いと使い方
No.7
Java&Spring記事人気No7
Spring
SpringのModelクラスとaddAttributeメソッドの使い方を完全ガイド!初心者でも安心
No.8
Java&Spring記事人気No8
Spring
SpringDataJPAのJPAクエリメソッド「EndingWith」の使い方を完全ガイド!初心者向け解説