코틀린에서 QueryDSL 사용

박태현·2025년 6월 19일
0

예약 프로젝트

목록 보기
4/8

코틀린에서 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()
    }
}
profile
꾸준하게

0개의 댓글