코틀린에서 QueryDSL를 사용하기 위해서는 반드시 kapt를 사용해야 합니다.
kapt( Kotlin Annotation Processing Tool )
왜 kapt를 사용해야할까 ?
QueryDSL은 컴파일 타임에 @Entity 클래스를 기반으로 Q클래스를 자동 생성하여 작동하는데,
Java에서는 annotationProcessor를 통해 이를 처리하지만, Kotlin은 컴파일 구조가 달라 annotationProcessor를 직접 사용할 수 없기 때문에 Kotlin에서는 kapt를 사용하여 QueryDSL의 Q클래스가 생성되도록 지원
따라서, kapt 의존성도 같이 설정해주어야 함
의존성 코드
plugins {
kotlin("jvm") version "1.9.25"
kotlin("plugin.spring") version "1.9.25"
id("org.springframework.boot") version "3.5.0"
id("io.spring.dependency-management") version "1.1.7"
kotlin("plugin.jpa") version "1.9.25"
// for querydsl
kotlin("kapt") version "1.9.25"
}
group = "com.example"
version = "0.0.1-SNAPSHOT"
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
repositories {
mavenCentral()
}
dependencies {
...
// query dsl
implementation("com.querydsl:querydsl-jpa:5.0.0:jakarta") // QueryDSL의 JPA 지원 라이브러리
kapt("com.querydsl:querydsl-apt:5.0.0:jakarta") // QClass 자동 생성기
kapt("jakarta.annotation:jakarta.annotation-api") // @Generated 등 어노테이션 정의
kapt("jakarta.persistence:jakarta.persistence-api") // @Entity, @Id 등 JPA 어노테이션 정의
}
// querydsl QClass 저장 위치
val generated = file("src/main/generated")
// QClass 생성 디렉토리 설정, kapt가 이 디렉토리에 Q클래스를 생성
tasks.withType<JavaCompile> {
options.generatedSourceOutputDirectory.set(generated)
}
// Kotlin 소스셋에 QClass 포함
sourceSets {
main {
kotlin.srcDirs += generated
}
}
// Gradle clean 시 QClass 삭제 → 코드를 변경했을 때 QClass를 다시 생성할 수 있도록 클린하게 비워주는 작업
tasks.named("clean") {
doLast {
generated.deleteRecursively()
}
}
kotlin {
compilerOptions {
freeCompilerArgs.addAll("-Xjsr305=strict")
}
}
tasks.withType<Test> {
useJUnitPlatform()
}
QueryDSL 설정 클래스
@Configuration
class QueryDslConfig(
val em: EntityManager
) {
@Bean
fun queryFactory(): JPAQueryFactory {
return JPAQueryFactory(em)
}
}
기존의 JPQL 쿼리
interface PerformanceRepository: JpaRepository<Performance, Long>, PerformanceRepositoryCustom {
// @Query("SELECT s.performance FROM ScreenInfo s WHERE s.place.id = :placeId")
// fun findPerformancesByPlaceId(@Param("placeId") placeId: Long): List<Performance>
}
Query DSL로 변경
interface PerformanceRepositoryCustom {
fun findPerformancesByPlaceId(placeId: Long): List<Performance>
}
---
class PerformanceRepositoryImpl(
private val queryFactory: JPAQueryFactory
): PerformanceRepositoryCustom {
// 특정 영화관의 영화 목록 리스트 반환
override fun findPerformancesByPlaceId(placeId: Long): List<Performance> {
val screenInfo = QScreenInfo.screenInfo
return queryFactory
.select(screenInfo.performance)
.from(screenInfo)
.where(screenInfo.place.id.eq(placeId))
.fetch()
}
}