Line에서 JPA의 Criteria API를 이용한 동적 쿼리 생성을 조금더 직관적으로 사용하기 위해 Kotlin JDSL을 개발하고 오픈소스로 전환하였습니다.
Kotlin JDSL 여기를 보면 자세한 코드를 확인할 수 있습니다.
GitHub - line/kotlin-jdsl: Kotlin DSL for JPA Criteria API without generated metamodel and reflection.
Kotlin DSL for JPA Criteria API without generated metamodel and reflection. - GitHub - line/kotlin-jdsl: Kotlin DSL for JPA Criteria API without generated metamodel and reflection.
github.com
올해 1월 5일에 JPA 3.0 스팩을 지원하면서 스프링 부트 3.0.x 버전도 같이 추가 되었습니다.

스프링 부트 3.0 의 가장 큰 차이는 기존의 javax의 명칭이 jakarta로 변경되었다는 것입니다. 이에 따라 Kotlin JDSL도 jakarta 버전도 추가하였습니다.
이슈

공식 깃허브를 가서 확인해보면 spring에서 jdsl을 어떻게 사용하는지 나와있습니다. 제가 진행중인 프로젝트 스팩은 spring boot 3.0.4를 사용하고 있고 spring-data-jpa 3.0.3을 사용하고 있습니다. 처음 셋팅 방법을 몰라 구글링과 깃허브에서 다른 사람이 kotlin jdsl로 작업한 프로젝트를 찾아봤습니다.
공통적으로 build.gradle.kt을 찾아보면 다음과 같이 dependuncy를 추가하는 것을 확인 할 수 있었습니다.
dependencies {
...
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("com.linecorp.kotlin-jdsl:spring-data-kotlin-jdsl-starter:2.2.1.RELEASE")
...
}
위의 방법은 스프링 부트 2.x버전에서 사용하는 방법입니다.
Spring Boot 3.0.X에서는 다음과 같이 설정을 해줘야 합니다.
dependencies {
...
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("com.linecorp.kotlin-jdsl:spring-data-kotlin-jdsl-starter-jakarta:2.2.1.RELEASE")
...
}
Config 설정
동적 쿼리를 작성하려면 queryFactory를 이용해야 합니다. 이를 위해서 SpringDataQeuryFactory를 @Bean에 등록을 해야 합니다. 방법은 다음과 같습니다.
package com.metamarine.transformservice.common
import com.linecorp.kotlinjdsl.query.creator.CriteriaQueryCreatorImpl
import com.linecorp.kotlinjdsl.query.creator.SubqueryCreatorImpl
import com.linecorp.kotlinjdsl.spring.data.SpringDataQueryFactory
import com.linecorp.kotlinjdsl.spring.data.SpringDataQueryFactoryImpl
import jakarta.persistence.EntityManager
import jakarta.persistence.PersistenceContext
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
class JdslConfiguration(
@PersistenceContext
private val entityManager: EntityManager
) {
@Bean
fun queryFactory(): SpringDataQueryFactory {
return SpringDataQueryFactoryImpl(
criteriaQueryCreator = CriteriaQueryCreatorImpl(entityManager),
subqueryCreator = SubqueryCreatorImpl()
)
}
}
구현 예시
앞서 queryFactory를 Bean에 등록하였기 때문에 다음과 같이 Kotlin JDSL을 사용할 수 있습니다.
import com.linecorp.kotlinjdsl.querydsl.expression.col
import com.linecorp.kotlinjdsl.spring.data.SpringDataQueryFactory
import com.linecorp.kotlinjdsl.spring.data.listQuery
import com.linecorp.kotlinjdsl.spring.data.singleQuery
import com.metamarine.transformservice.domain.entity.Components
import com.metamarine.transformservice.domain.repository.query.ComponentsQueryRepository
import org.springframework.stereotype.Repository
@Repository
class ComponentsQueryRepositoryImpl(
private val queryFactory: SpringDataQueryFactory
): ComponentsQueryRepository {
override fun findByIdOrNull(componentId: Long): Components? {
return queryFactory.singleQuery {
select(entity(Components::class))
from(entity(Components::class))
where(col(Components::id).equal(componentId))
}
}
override fun findAll(): List<Components> {
return queryFactory.listQuery {
select(entity(Components::class))
from(entity(Components::class))
}
}
}
'Dev' 카테고리의 다른 글
Sync/Async와 Blocking/NonBlocking 성능 비교 (0) | 2024.05.31 |
---|---|
Multi-Thread 동시성 제어 방법 (0) | 2024.05.03 |
그리드 분할을 이용한 Weighted A* 성능 최적화 (0) | 2023.04.01 |
A Star Algorithm(A*, Weighted A*) (0) | 2023.04.01 |
IntelliJ 한글 깨짐 원인 & 해결 (0) | 2023.03.11 |