관리 메뉴

피터의 개발이야기

[Kotlin] Kotlin JDSL 문법 정리 본문

Programming/Kotlin

[Kotlin] Kotlin JDSL 문법 정리

기록하는 백앤드개발자 2024. 8. 16. 10:10
반응형

ㅁ 들어가며

ㅇ 신규 프로젝트에서 Kotlin JDSL을 사용하게 되어, 관련 공부를 하면서 참조 목록과 주요 문법을 정리해 보았다.

 

ㅁ Kotlin JDSL란?

 Kotlin JDSL은 Kotlin의 DSL(Domain Specific Language) 기능을 활용하여 JPA Criteria API를 더 직관적이고 간결하게 작성할 수 있도록 한다. KProperty를 사용하여 메타모델을 사용하지 않고도 안전한 코드를 작성할 수 있다.

 

ㅁ 주요문법

@Entity
data class Order(
    @Id @GeneratedValue
    val id: Long,
    val purchaserId: Long,
    val amount: Double
)

ㅇ Order를 가정해 보자.

 

val query = queryFactory.select(entity(Order::class)) {
    where(
        and(
            col(Order::purchaserId).equal(purchaserId),
            col(Order::amount).greaterThan(minAmount)
        )
    )
}

ㅇ Kotlin JDSL을 사용하여 select 쿼리를 작성한다.

 

ㅁ Subquery와 Join

val subquery = queryFactory.subquery(Order::class) {
    select(col(Order::id))
    where(col(Order::amount).greaterThan(100.0))
}

val query = queryFactory.select(entity(Order::class)) {
    where(col(Order::id).`in`(subquery))
}

ㅇ Kotlin JDSL은 Criteria API에서 지원하는 다양한 쿼리 형태를 지원한다. Subquery나 Join도 쉽게 작성할 수 있다.

 

val query = jpql {
    select(
        path(Employee::employeeId),
    ).from(
        entity(Employee::class),
        join(Employee::departments),
    ).where(
        type(entity(Employee::class)).eq(FullTimeEmployee::class)
    ).groupBy(
        path(Employee::employeeId),
    ).having(
        count(Employee::employeeId).greaterThan(1L),
    ).orderBy(
        count(Employee::employeeId).desc(),
        path(Employee::employeeId).asc(),
    )
}

Select statement에서 제공되는 예문이다.

ㅇ SQL문과 흡사한 구조로 되어 있어 가독성이 있다.

ㅇ groupBy, having, orderBy가 지원된다.

 

ㅁ Update

val query = jpql {
    update(
        entity(Book::class)
    ).set(
        path(Book::price)(BookPrice::value),
        BigDecimal.valueOf(100)
    ).set(
        path(Book::salePrice)(BookPrice::value),
        BigDecimal.valueOf(80)
    ).where(
        path(Book::isbn).eq(Isbn("01"))
    )
}

Update statement에서 제공하는 예문이다.

 

ㅁ Delete

val query = jpql {
    deleteFrom(
        entity(Book::class),
    ).where(
        path(Book::publishDate).ge(OffsetDateTime.parse("2023-06-01T00:00:00+09:00")),
    )
}

 delete statement에서 제공해주는 예문이다.

 

ㅁ 조건 표현식(conditional expression)

ㅇ Kotlin JDSL은 JPQL의 conditional expression을 표현하기 위해 Predicate 인터페이스를 가지고 있다.

ㅇ 논리 조건, 비교연산, Null, Like, Between, In, Exists의 사용법은 Predicates을 참조하였다.

 

Equal / Not Equal: 두 값이 같은지 비교한다.

// equal
val equalPredicate = entity.age.equal(30)

// notEqual
val notEqualPredicate = entity.name.notEqual("Peterica")

 

Greater Than / Less Than: 값의 크기를 비교한다.

val greaterThanPredicate = entity.salary.greaterThan(50000)
val lessThanPredicate = entity.salary.lessThan(100000)

 

Greater Than or Equal / Less Than or Equal: 값의 크기 또는 같음을 비교한다.

val greaterThanOrEqualPredicate = entity.age.greaterThanOrEqual(18)
val lessThanOrEqualPredicate = entity.age.lessThanOrEqual(65)

 

Like: 문자열 패턴을 비교한다.

val likePredicate = entity.name.like("%Smith%")

 

Between: 값이 특정 범위 내에 있는지 확인한다.

val betweenPredicate = entity.age.between(18, 30)

 

In: 값이 특정 컬렉션에 포함되어 있는지 확인한다.

val inPredicate = entity.status.`in`(listOf("ACTIVE", "INACTIVE"))

 

Is Null / Is Not Null: 값이 null인지 아닌지 확인한다.

val isNullPredicate = entity.address.isNull()
val isNotNullPredicate = entity.phoneNumber.isNotNull()

 

ㅁ 조합 조건

ㅇ Kotlin JDSL에서는 여러 조건 표현식을 조합하여 복합 조건을 만들 수 있다. and와 or 연산자를 사용하여 여러 조건을 결합할 수 있다.

val combinedPredicate = 
   entity.age
     .greaterThan(18)
     .and(entity.status.equal("ACTIVE"))

 

ㅁ 마무리

  이러한 기능을 통해 Kotlin JDSL은 JPQL을 더욱 유연하고 직관적으로 사용할 수 있게 해준다. 복잡한 조건을 쉽게 표현할 수 있어, 데이터베이스 쿼리를 작성하는 데 있어 생산성을 높일 수 있다. 그리고 spring-data-jpa 소스를 제공하고 있다.

 

ㅁ 함께 보면 좋은 사이트

Kotlin JDSL Doc

Kotlin JDSL 사용해보기

Kotlin JDSL: Kotlin을 이용해 좀 더 쉽게 JPA Criteria API를 작성해 봅시다

 

반응형
Comments