티스토리 뷰

한번 QueryDSL을 어떻게 사용하는지와 기본적인 사용방법에 대해서 알아보자.

코드는 현재 만들고 있는 게시판 API에다가 추가할 예정이다. 코드는 깃허브에 있다. 

 

환경설정

먼저 queryDSL의 버전을 나타내는 코드를 추가하자. 

 

buildscript {
   ext {
      queryDslVersion = "5.0.0"
   }
}

 

그리고 플러그인에 아래코드를 추가하자. 

 

id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"

 

dependencies에 아래코드를 추가하자. 

 

implementation "com.querydsl:querydsl-jpa:${queryDslVersion}"
implementation "com.querydsl:querydsl-apt:${queryDslVersion}"

 

그리고 밑에 설정을 더 추가해주자. 

 

def querydslDir = "$buildDir/generated/querydsl"
// JPA 사용 여부와 사용할 경로를 설정
querydsl {
	jpa = true
	querydslSourcesDir = querydslDir
}
// build 시 사용할 sourceSet 추가
sourceSets {
	main.java.srcDir querydslDir
}
// querydsl 컴파일시 사용할 옵션 설정
compileQuerydsl{
	options.annotationProcessorPath = configurations.querydsl
}
// querydsl 이 compileClassPath 를 상속하도록 설정
configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
	querydsl.extendsFrom compileClasspath
}

 

추가하면 오른쪽 상단쯤에 코끼리 모양이 뜰 것이다. 클릭해주자. 

만약 뜨지 않는다면 맨 오른쪽에 Gradle을 클릭하고 Reload All Gradle Project를 클릭해 빌드해주자.

 

 

 

그리고 Tasks -> other -> compileQuerydsl을 클릭하면 뭐가 실행될 것이다. 

 

 

만약 여기서 오류가 났으면 JDK 오류일 가능성이 있다. 

나는 이 프로젝트를 생성할 때 자바 버전을 17로 해놓고 돌릴 때는 11 JDK로 돌렸었다. 

그래서 다시 17로 바꿔주니 제대로 실행되었다. 

 

그리고 왼쪽에 build -> generated를 열어보면 QueryDSL을 사용하기 위한 QClass들이 생성된다. 

 

 

여기까지가 QueryDSL을 사용하기 위한 환결설정들이다. 

그럼 QueryDSL을 어떻게 사용하는지 알아보자. 

 

QueryDSL 기본적인 사용방법

나는 repository 패키지 안에 BoardQuerydslRepository라고 만들었다. 이름은 나중에 바꿀 예정이다. 

 

 

일단 QueryDSL을 사용하려면 먼저 JPAQuery 객체를 생성해주어야 한다. 

이때 엔티티 매니저를 스프링으로부터 주입받아서 생성자에게 넘겨준다. 이렇게 하면 코드를 작성할 준비가 완료되었다. 

 

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Repository
public class BoardQuerydslRepository {

    @PersistenceContext
    EntityManager em;

    JPAQuery query;
    
    public BoardQuerydslRepository(EntityManager em) {
    	this.em = em;
        this.query = new JPAQuery(em);
    }
}

 

다음으로는 사용할 쿼리 타입을 생성하는데, 생성자한테는 별칭을 주면 된다. 이 별칭을 JPQL에서 별칭으로 사용한다. 

 

다시 JPQL에 대해 잠깐 말해보자면,

 

결국 QueryDSL은 JPQL쿼리의 오류를 컴파일 시점에서 바로잡고 문자가 아닌 코드로 쿼리를 짜기 위해서 나온 것이고, 실행하면 JPQL로 실행된다. 위에서 말했던 JPQL에서의 별칭이란 DB에서 사용하는 AS와 같다. JPQL은 별칭을 필수로 사용해야 하며, 만약 별칭을 사용하지 않으면 실행시점에 오류가 뜬다. 

 

별칭을 사용하지 않은 코드

select username Member m

 

별칭을 사용한 코드

select m.username from Member as m

 

as는 생략이 가능하다. 

그렇기에 사용할 쿼리타입에 별칭을 넣어줌으로써 JPQL로 실행될때 넣어준 별칭으로 사용하는 것이다. 

 

QueryDSL은 기본 인스턴스를 사용할 수 있다. 

 

직접 별칭을 지정해서 사용

QMember member = new QMember("m");

 

기본 인스턴스를 사용

QMember member = QMember.member;

 

만약 같은 엔티티를 조인하거나 서브쿼리에 사용을 한다면, 즉 별칭이 똑같은 쿼리타입이 존재한다면 이때는 별칭을 직접 지정해야 한다. 

 

기본 인스턴스를 사용하면 import static 을 활용해서 코드를 간결하게 작성할 수 있다. 

 

직접 별칭을 넣어줄 때의 코드

import api.boardAPI.domain.member.domain.QMember;
import com.querydsl.jpa.impl.JPAQuery;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class BoardQuerydslRepository {

    @PersistenceContext
    EntityManager em;

    JPAQuery query = new JPAQuery(em);
    QMember member = new QMember("m");
}

 

기본 인스턴스를 사용하고 import static을 활용할 때의 코드

import static api.boardAPI.domain.member.domain.QMember.member;
import com.querydsl.jpa.impl.JPAQuery;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class BoardQuerydslRepository {

    @PersistenceContext
    EntityManager em;

    JPAQuery query = new JPAQuery(em);
}

 

쿼리타입 선언문이 없어도 된다. 

그럼 간단하게 게시글 제목이 "테스트"인 게시글들을 조회하는 코드를 작성하고 마치겠다. 

 

@Repository
public class BoardQuerydslRepository {

    @PersistenceContext
    EntityManager em;
    private final JPAQueryFactory query;

    public BoardQuerydslRepository(EntityManager em) {
        this.em = em;
        this.query = new JPAQueryFactory(em);
    }

    public List<Board> findByTitle() {
        return query
                .select(board)
                .from(board)
                .where(board.title.eq("테스트"))
                .fetch();
    }
}

 

JPAQuery와 JPAQueryFactory의 차이는 둘다 JPAQuery를 생성하는 것은 같지만 코드 간결성과 지원하는 것들이 더 많기 때문에 JPAQueryFactory를 사용하는 것이 더 좋다. 

 

코드를 보면 한눈에 봐도 "board라는 테이블에서 제목이 테스트와 같은 board를 조회한다" 라고 알 수가 있다. 

그럼 한번 실행까지 해보자. 서비스로직을 작성한다.

 

 

그리고 컨트롤러로 조회하는 매핑을 만들어주자. 

 

 

Wrap은 List 반환을 Object로 감싸서 보내는 제네릭클래스기 때문에 신경쓰지 않아도 된다.

그리고 Postman으로 조회해보면 아래와 같이 잘 동작하는 것을 볼 수 있다. 

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday