본문 바로가기
DB&JPA

[QueryDSL] SpringBoot3 버전 QueryDSL 설정하기

by 덩라 2023. 6. 30.

JPA 혹은 Spring Data JPA 를 사용해서 프로젝트를 진행하다 보면, 특정 경우에서 오는 불편함을 지울 수 없습니다.

예를 들면, 검색쿼리 같이 조건문이 여러 조합으로 되는 경우나, Entity 를 조회하는 것이 아닌 DTO를 조회하는 경우 등과 같은 경우가 있습니다. 이런 단점을 보완하기 위해, JPA를 사용하는 곳에선 QueryDSL 을 같이 사용하는 곳이 많다고 합니다.

 

저 또한, QueryDSL 을 사용하면서 사이드 프로젝트를 진행하는데, 설정방법을 매번 찾아보기 번거로워 블로깅해봅니다.


0. 구성환경

QueryDSL 에서는 maven 에 대한 가이드는 제공하면서... gradle에 대한 가이드는 제공해주지 않습니다...

(이유는 모르겠슴돠...ㅠ 아시는 분 댓글 부탁드려용 ㅎ)

 

그래서 기존에 QueryDSL 설정을 구글에 검색하면 많은 방법이 나오지만, 대부분 SpringBoot 2.x.x 버전에 java 1.8 혹은 11 기준인 글이 많습니다. 

하지만, 제가 설정한 환경은 SpringBoot 3.1.0 / java 17 이니 참고 부탁드립니다.

 

출처 : https://lemontia.tistory.com/1089

 

[springboot 3.x, querydsl] QClass 생성 및 경로 설정

springboot 2.x 와 달라진점이 있다면 plugins 에 편의상으로 추가했던 다음항목을 사용하지 못하면서 문제가 시작된다. id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" 위 플러그인을 사용하면 compileQuerdsl

lemontia.tistory.com

 

1. build.gradle 설정

QueryDSL dependency를 추가하기 위해서 아래 내용을 추가해줘야 합니다.

dependencies {
    // -- 중략 -- //

    // QueryDSL
    implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
    annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta'
    annotationProcessor 'jakarta.annotation:jakarta.annotation-api'
    annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
}

def querydslSrcDir='src/main/generated'
clean {
    delete file(querydslSrcDir)
}
tasks.withType(JavaCompile) {
    options.generatedSourceOutputDirectory = file(querydslSrcDir)
}

QueryDSL 은 @Entity 이 붙은 class 와 그 class 안에 포함된 class 이름 앞에 Q 를 붙인 Q타입 class 를 생성하고, 이것을 사용할 수 있게 지원해줍니다. 

 

위와 같이 dependency를 적용한 후, 인텔리제이의 우측 gradle 메뉴에서 "compileJava" 를 실행합니다.

그럼 하단 콘솔창에 성공표시와 함께, "src/main/generated" 밑에 Q타입의 entity 들이 생성되어 있습니다.

compileJava gradle 실행
compileJava gradle 실행 결과

 

 

2. 간단한 예제 테스트

제가 현재 개발 중인 프로젝트는 상단 메뉴를 DB에서 관리하도록 설계되어 있어, 모든 최상위 메뉴 정보를 조회하는 쿼리를 아래와 같이 작성하였습니다.

-- JPQL 버전
select m from Menu m where m.parent is null order by m.order

 

위 쿼리를 반환하도록 하는 QueryDSL Repository 를 아래와 같이 작성해봤습니다.

@Repository
public class MenuQueryRepository {
    private final JPAQueryFactory queryFactory;

    public MenuQueryRepository(EntityManager em) {
        this.queryFactory = new JPAQueryFactory(em);
    }

    public List<Menu> findTopMenus() {
        return queryFactory.selectFrom(QMenu.menu)
                .where(
                        QMenu.menu.parent.isNull()
                )
                .orderBy(
                        QMenu.menu.order.asc()
                )
                .stream().toList();
    }
}

 

QueryDSL의 JPAQueryFactory는 JPA에서 사용하는 EntityManager 를 주입받아 JPQL Builder 역할을 수행해줍니다.

JPQL 작성 시 단점 중 하나로 뽑히는 순수 문자열로 쿼리를 작성하여 쿼리를 잘 못 작성한 경우, 메서드를 실행해보기 전까진 오류를 발견할 수 없다는 점을 QueryDSL 은 모두 컴파일단계에서 문법오류를 발생시킴으로써 앞의 단점을 극복합니다.

 

위 메서드의 테스트코드를 작성하고 테스트를 실행해봄으로써 아래와 같이 쿼리가 동작한다는 것을 알 수 있습니다.

댓글