JPQL with Kotlin JDSL

Requirements

Kotlin JDSL์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Java 8 (ํ˜น์€ ๊ทธ ์ด์ƒ) ๊ณผ Kotlin 1.7 (๊ทธ ์ด์ƒ)์ด ์š”๊ตฌ๋ฉ๋‹ˆ๋‹ค.

Configure the repositories

Kotlin JDSL dependency๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „์— maven repository๊ฐ€ ์ถ”๊ฐ€ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Release

Kotlin JDSL์˜ release๋Š” ๋ชจ๋‘ Maven central repository์— ์—…๋กœ๋“œ ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” maven repository๊ฐ€ ๋นŒ๋“œ ์Šคํฌ๋ฆฝํŠธ์— ์ถ”๊ฐ€ ๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

repositories {
    mavenCentral()
}

Snapshot

Kotlin JDSL์˜ snapshot์€ ๋ชจ๋‘ OSS snapshot repository์— ์—…๋กœ๋“œ ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” OSS snapshot repository๊ฐ€ ๋นŒ๋“œ ์Šคํฌ๋ฆฝํŠธ์— ์ถ”๊ฐ€ ๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

repositories {
    maven(url = "https://oss.sonatype.org/content/repositories/snapshots")
}

Add Kotlin JDSL dependencies

Core dependencies

Kotlin JDSL์„ ์‹คํ–‰์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ dependency๋“ค์ด ํ•„์ˆ˜๋กœ ์š”๊ตฌ๋ฉ๋‹ˆ๋‹ค.

  • jpql-dsl: JPQL ์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” DSL

  • jpql-render: DSL๋กœ ๋งŒ๋“  ์ฟผ๋ฆฌ๋ฅผ String์œผ๋กœ ๋ณ€ํ™˜์‹œ์ผœ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

dependencies {
    implementation("com.linecorp.kotlin-jdsl:jpql-dsl:3.5.5")
    implementation("com.linecorp.kotlin-jdsl:jpql-render:3.5.5")
}

Support dependencies

Kotlin JDSL์€ DSL๋กœ ์ƒ์„ฑ๋œ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” Support dependency๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ฐ JPA ์ œ๊ณต์ž์— ๋งž์ถฐ ๋‹ค์Œ dependency๋“ค ์ค‘์—์„œ ์„ ํƒํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • hibernate-support: Hibernate๋ฅผ ํ†ตํ•ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๋„์›€์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ.

  • eclipselink-support: EclipseLink๋ฅผ ํ†ตํ•ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๋„์›€์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ.

  • spring-batch-support: Spring Batch์™€ ํ•จ๊ป˜ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๋„์›€์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ.

  • spring-data-jpa-support: Spring Data Jpa์™€ ํ•จ๊ป˜ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๋„์›€์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ.

  • hibernate-reactive-support: Hibernate Reactive์™€ ํ•จ๊ป˜ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๋„์›€์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ.

Javax

javax ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ dependency๋“ค ์ค‘์—์„œ ์„ ํƒํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • hibernate-javax-support: Hibernate๋ฅผ ํ†ตํ•ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๋„์›€์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ.

  • eclipselink-javax-support: EclipseLink๋ฅผ ํ†ตํ•ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๋„์›€์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ.

  • spring-batch-javax-support: Spring Batch์™€ ํ•จ๊ป˜ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๋„์›€์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ.

  • spring-data-jpa-javax-support: Spring Data Jpa์™€ ํ•จ๊ป˜ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๋„์›€์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ.

  • hibernate-reactive-javax-support: Hibernate Reactive์™€ ํ•จ๊ป˜ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ๋„์›€์„ ์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ.

Build a query

jpql()์—์„œ select()๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์œผ๋กœ select statement๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

val query = jpql {
    select(
        path(Author::authorId),
    ).from(
        entity(Author::class)
    )
}

์œ ์‚ฌํ•˜๊ฒŒ Kotlin JDSL์€ ๋‹ค๋ฅธ statement๋ฅผ ์œ„ํ•œ ํ•จ์ˆ˜๋„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค: update statement, delete statement. ๋” ๋งŽ์€ ์˜ˆ์ œ๋ฅผ ๋ณด๊ณ  ์‹ถ์œผ์‹œ๋ฉด GitHub์— examples์„ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

์ถ”๊ฐ€๋กœ custom DSL์„ ํ†ตํ•ด ๋ณธ์ธ๋งŒ์˜ DSL์„ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

Execute the query

์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋“  ๋’ค์—๋Š” RenderContext๋ฅผ ์ด์šฉํ•ด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด JpqlRenderContext๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

val context = JpqlRenderContext()

val renderer = JpqlRenderer()

val rendered = renderer.render(query, context)

val jpaQuery: Query = entityManager.createQuery(rendered.query).apply {
    rendered.params.forEach { (name, value) ->
        setParameter(name, value)
    }
}

val result = jpaQuery.resultList

RenderContext๋Š” ์ฟผ๋ฆฌ๋ฅผ String์œผ๋กœ ๋žœ๋”๋งํ•  ์ˆ˜ ์žˆ๋Š” ์š”์†Œ๋“ค์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. Kotlin JDSL์€ RenderContext์˜ default ๊ตฌํ˜„์ฒด๋กœ JpqlRenderContext๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

JpqlRenderer๋Š” RenderContext๋ฅผ ์ด์šฉํ•ด ์ฟผ๋ฆฌ๋ฅผ String์œผ๋กœ ๋žœ๋”๋งํ•ฉ๋‹ˆ๋‹ค. JpqlRenderer๋Š” String์œผ๋กœ ๋žœ๋”๋ง๋œ query์™€ ์ฟผ๋ฆฌ์— ํฌํ•จ๋œ parameters๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” JpqlRendered๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. JpqlRenderer๋Š” ์ƒํƒœ๋ฅผ ๊ฐ€์ง€์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ์ฒด์˜ ์žฌ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ ๋ฉ€ํ‹ฐ ์“ฐ๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ์— ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

RenderContext๋ฅผ ๋งŒ๋“œ๋Š” ๋น„์šฉ์€ ๋น„์‹ธ๊ธฐ ๋•Œ๋ฌธ์— ํ•œ๋ฒˆ๋งŒ ๋งŒ๋“ค๊ณ  ์ด๋ฅผ ์žฌํ™œ์šฉํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค. RenderContext๋Š” immutable ๊ฐ์ฒด๋กœ ๋ฉ€ํ‹ฐ ์“ฐ๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ์— ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

Kotlin JDSL Support๋Š” ์œ„ ์‹คํ–‰ ๊ณผ์ •์„ ๊ฐ„๋žตํ™” ์‹œํ‚จ EntityManager์˜ extension function๋“ค์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•ด ์ฟผ๋ฆฌ๋ฅผ ์‰ฝ๊ฒŒ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

val context = JpqlRenderContext()

val jpaQuery: Query = entityManager.createQuery(query, context)

val result = jpaQuery.resultList

Last updated