【JPA/Querydsl】必要なカラムだけDTOにマッピングする(Projections.constructor)

|

queryDSLで「SELECT * FROM…」するのではなく、必要なカラムだけ取得する方法をお伝えします。

クエリチューニングの一環としてでSELECTする対象を絞り込む時(Key LookUpを減らして実行計画改善する時とか)に便利なTipになってます!

[st-myblock id=”447″]

解決したい課題

  • JPA + 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()

公式ドキュメントも参考にしてみてください!

https://javadoc.io/doc/com.querydsl/querydsl-core/4.0.5/com/querydsl/core/types/Projections.html

サンプル実装

より上級記事も書いてます!