Spring DATAのJPA Repositoryを使っているが、戻り値をJPA Entity全体ではなく、任意のフィールドだけにしたいという話があった。
単純にSQLのように SELECT フィールド, フィールド...
すると Object
の配列になるが、それは避けて任意のDTOやインターフェースにする方法を聞かれたのでメモ。
DTOの場合
必要なフィールドを引数に取る、コンストラクタをもったクラスを用意する。
package example; @Getter @AllArgsConstructor class ResultDto { private String id; private String name; }
@Query
内で、 new DTOの完全修飾クラス名(コンストラクタ引数...)
を書くと、メソッドの戻り値をDTOにできる。
@Query("SELECT new example.ResultDto(e.id, e.name) FROM EntityClass e") List<ResultDto> findResultDtoAll();
インターフェースの場合
Getterだけのインターフェースを用意。
interface ResultInterface {
String getId();
String getName();
}
@Query
内で、 SELECT エンティティクラス.フィールド...
を書くと、メソッドの戻り値をインターフェースにできる。
@Query("SELECT e.id, e.name FROM EntityClass e") List<ResultInterface> findResultInterfaceAll();
ちなみに実態としては、java.sql.ResultSet に動的プロキシでインターフェースをかぶせている模様。エンティティクラスのフィールドと型が合わない場合などは、Getterメソッド呼び出し時に例外が発生する。
参考
Stack Overflowに質問があり、DTOの場合とインターフェースの場合の両方が記載されている。