これは何?
queryDSLで「SELECT * FROM...」するのではなく、必要なカラムだけ取得する方法をお伝えします。
クエリチューニングの一環としてでSELECTする対象を絞り込む時(Key LookUpを減らして実行計画改善する時とか)に便利なTipになってます!
解決したい課題
- queryDSLで必要なカラムだけ取得したい
- その際、@Entityクラスではなく、自分で作ったDTO的なクラスに結果をマッピングしたい
そもそもqueryDSLとは
JPA+HibernateでSQLを実装する際、型安全な実装を可能にしてくれるライブラリ。
Querydsl - Unified Queries for Java
結論:Projections.constructorを使う
Projectiosns.constructor
というメソッドによって、DTOに結果をマッピングします。
TABLE
↓このbook
テーブルに対して、release_date以外のデータを取ってくることを想定します。
CREATE TABLE book ( id VARCHAR(255) PRIMARY KEY, title VARCHAR(255) NOT NULL, author VARCHAR(255) NOT NULL, release_date DATETIME NOT NULL //この行は今回取得したくない!!! );
TABLEクラス
import java.time.LocalDateTime import javax.persistence.Entity import javax.persistence.Id import javax.persistence.JoinColumn import javax.persistence.OneToMany import javax.persistence.Table @Entity @Table(name = "book") class BookEntity( @Id var id: String? = null, val title: String? = null, val author: String? = null, val releaseDate: LocalDateTime? = null, )
DTOクラス
class BookDto( val id: String, val title: String, val author: String, )
クエリメソッド
select句の中にProjections.constructorメソッドを入れて、DTOにマッピングします。
import com.querydsl.core.types.Projections import com.querydsl.jpa.impl.JPAQueryFactory import com.sample.infra.jpa.entity.QBookEntity //自動生成されるQEntity import com.sample.usecase.query.BookDto val queryFactory: JPAQueryFactory = JPAQueryFactory(entityManager); //entityManagerはjavax.persistence.EntityManager val book = QBookEntity.bookEntity //自動生成されるQEntity val result = queryFactory.select( Projections.constructor( BookDto::class.java, book.id, book.author, book.title, ) ).from(book).where(book.id.eq(id)).fetchOne()
公式ドキュメントも参考にしてみてください!