kotlin에서 queryDSL 사용하기

 implementation("com.querydsl:querydsl-jpa:5.0.0:jakarta")
 implementation("com.querydsl:querydsl-apt:5.0.0:jakarta")

build.gradle.kts 파일에 아래 내용을 추가해준다.

 

plugins {
	kotlin("kapt") version "1.9.23"
}

dependencies {
    // querydsl
    implementation("com.querydsl:querydsl-jpa:5.1.0:jakarta")
    implementation("com.querydsl:querydsl-apt:5.1.0:jakarta")
    kapt("com.querydsl:querydsl-apt:5.1.0:jakarta")
    kapt("org.springframework.boot:spring-boot-configuration-processor")

    implementation("org.hibernate:hibernate-core:6.1.0.Final")

}

 

kapt 플러그인을 추가해 kotlin에서도 querydsl을 사용할 수 있게 해준다.

 

gradle clean 후 build를 해주면 build > classes > generated > source > kapt 경로에 Q클래스들이 생성된다. 

 

springboot3으로 버전이 올라가면서 jdk는 17 버전을 선택하게 됨. 17버전부터는 javax -> jakarta 패키지로 변경되어 의존성 추가 시 뒤에 classifier에 jakarta를 표기해야함.

 implementation("com.querydsl:querydsl-jpa:5.0.0:jakarta")
 implementation("com.querydsl:querydsl-apt:5.0.0:jakarta")

 

 

kotlin + queryDSL를 사용해서 개발하던 중 아래와 같은 오류를 마주함.

and token 'SEPARATOR', no viable alternative at input 'select table_a.cstCd, table_a.cstNm, table_a.orderNo, group_concat(table_a.goodsSno *SEPARATOR '|')'
from shopOrder shopOrder

 

mysql에서 사용하던 group_concat 함수를 아래와 같이 등록하여 사용하던 중에 group_concat의 기본 separator가 콤마라서 |로 바꾸려고 하는 중에 separator는 사용할 수 없는 명령어라는 오류 발생 여러가지 방법으로 시도하려고 했으나.. 해결되지 않아 어쩔 수 없이 자바단에 함수를 생성하여 replace하는 것으로 변경

 

override fun contributeFunctions(functionContributions: FunctionContributions) {
    functionContributions.functionRegistry.register("GROUP_CONCAT", StandardSQLFunction(
        "group_concat",
        StandardBasicTypes.STRING
    ))
}

 

mysql의 group_concat을 querydsl에서 사용하려면 함수를 등록해야 사용할 수 있다. 그렇지 않으면 아래와 같은 에러 발생

2024-07-03T14:41:55.736+09:00 ERROR 54176 --- [nio-1899-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.QueryException: No data type for node: org.hibernate.hql.internal.ast.tree.MethodNode 
 \-[METHOD_CALL] MethodNode: '('
    +-[METHOD_NAME] IdentNode: 'group_concat' {originalText=group_concat}
    \-[EXPR_LIST] SqlNode: 'exprList'
       \-[DOT] DotNode: 'or0_.goods_sno' {propertyName=goodsSno,dereferenceType=PRIMITIVE,getPropertyPath=goodsSno,path=Ord.goodsSno,tableAlias=or0_,className=com.xxxx.orderapi.domain.order.entity.Ord,classAlias=Ord}
          +-[ALIAS_REF] IdentNode: 'or0_.order_no, or0_.goods_sno' {alias=ord, className=com.xxxxx.orderapi.domain.order.entity.ord, tableAlias=or0_}
          \-[IDENT] IdentNode: 'gdmGoodsSno' {originalText=gdmGoodsSno}
 [select ord.cstCd, ord.orderNo, ord.invoiceNo, ord.invoiceCompanySno, group_concat(ord.goodsSno)
from com.xxxxx.rderapi.domain.order.entity.Ord ord]] with root cause

 

아래처럼 DBDiaclect을 extends한 후 function을 추가하여 group_concat을 사용할 수 있도록 등록함.


class CustomMySQLDialect: MariaDBDialect() {

    override fun contributeFunctions(functionContributions: FunctionContributions) {
        functionContributions.functionRegistry.register("GROUP_CONCAT", StandardSQLFunction(
            "group_concat",
            StandardBasicTypes.STRING
        ))
    }
}

 

반응형