QueryDSL 사용하기 – 함수

By | 2022년 7월 27일
Table of Contents

QueryDSL 사용하기 – 함수

DB 독립적인 방법

QueryDSL 에서 지원하는 함수인 경우

ANSI 함수의 경우 QueryDSL 에서 지원해 주기에,
바로 함수를 사용할 수 있다.

    public List<String> upper() {
        System.out.println("DSL Called");
        return jpaQueryFactory
                .select(user.username.upper().as("username"))
                .from(user)
                .where(user.username.eq("Lee")).fetch();
    }

Projections 의 생성자 패턴 이용

참조

함수의 결과값이 리턴값으로만 쓰이고,
where 조건절에서 사용되지 않는 경우 DTO 생성자에서 변환해 줄 수 있다.

DB 종속적인 방법

QueryDSL 에서 지원하지 않는 함수인데,
또 where 조건절에서 사용되어야 하는 경우,
DB 종속적인 방법이지만 대안이 없으므로 이 방법을 사용한다.

DB 종속적인 방법에도 몇가지 방법이 있는 듯 하지만,
어차피 DB 변경시 추가작업이 필요한 것은 마찬가지이므로,
한가지만 소개합니다.

함수명이 등록된 경우

    public List<String> substring() {
        return jpaQueryFactory
                .select(
                        Expressions.stringTemplate(
                                "function('substring', {0}, {1})",
                                user.email,
                                Expressions.constant(2))
                )
                .from(user)
                .where(user.username.eq("Lee")).fetch();
    }

함수명이 등록되지 않은 경우

함수명이 등록되어 있지 않은 경우 오류가 발생한다.
또, 커스텀 함수(custom function) 을 사용해야 하는 경우도 오류가 발생한다.

    @Override
    public List<String> left() {
        return jpaQueryFactory
                .select(
                        Expressions.stringTemplate(
                                "function('left', {0}, {1})",
                                user.email,
                                Expressions.constant(2))
                )
                .from(user)
                .where(user.username.eq("Lee")).fetch();
    }

이럴 땐 Dialect 를 상속 후, 함수명을 등록해 주어야 한다.

public class MyMariadbDialect extends MariaDB103Dialect {

    public MyMariadbDialect() {
        super();
        registerFunction(
                "left",
                new StandardSQLFunction("left", StandardBasicTypes.STRING)
        );

        // // Expressions.simpleTemplate(String.class, "사용자정의함수명({0})", user.email)
        // registerFunction("사용자정의함수명",
        //         new SQLFunctionTemplate(
        //             StandardBasicTypes.STRING,
        //             "사용자정의함수명(?1)")
        //         );

        // 컬럼 타입 추가
        // registerColumnType( Types.TIMESTAMP, "datetime(6)" );
    }
}
spring:
  jpa:
    database-platform: com.example.querydsltest.config.MyMariadbDialect

SqlServer

SqlServer 의 경우 dbo 도 같이 붙여주어야 한다.

public class MySqlServerDialect extends SQLServer2012Dialect {

    public MySqlServerDialect() {
        super();

        registerFunction(
                "dbo.getCateCodeFullDepthName",
                new StandardSQLFunction("dbo.getCateCodeFullDepthName", StandardBasicTypes.STRING)
        );
    }
}
Expressions.stringTemplate(
    "dbo.getCateCodeFullDepthName({0})",
    itemDisplayCategoryItemEntity.id.id).as("categoryFullName")

답글 남기기