QueryDSL :Query Domain Specific Lanauage
QueryDSL이란 무엇인가?
QueryDSL은 자바 코드를 기반으로 하여 쿼리를 작성 할 수 있도록 도와주는 도구로 직관적이고 유연한 쿼리 작성을 가능하게하기 때문에, 복잡한 쿼리나 동적 쿼리 또는 여러 테이블 간의 조인을 통한 값 조회가 요구되는 쿼리 생성이 필요한 경우 등에 JPQL(=JPA Query Lanauage)과 함께 널리 사용되는 라이브러리입니다.
** 자바에서는 데이터베이스 관련 작업을 위해 기본적으로 jpaRepository가 사용되는데, jpaRepository는 자바에서 데이터베이스와 연동된 작업을 하기에 매우 편리하고 간단하지만, 단순 CRUD 위주의 작업을 벗어난 복잡한 쿼리나 혹은 동적 쿼리 또는 여러 테이블과 조인이 필요한 경우 등에는 jpaRepository 만으로는 작업에 어려움이 있어서 해당 작업이 필요한 경우 JPQL과 QueryDSL을 사용합니다.
** 동적쿼리
동적쿼리란 실행 시점에 쿼리의 형태가 변경될 수 있는 쿼리를 의미합니다. 예를 들어 mybatis로 작성된 아래의 쿼리를 보면, title과 sub_category에 대한 조건은 파라미터의 값이 존재하거나 같은 경우에만 조건으로 구현이 되고, title의 값이 존재하지 않거나, category의 값이 Daily가 아닌 경우에 쿼리의 조건은 DEL_YN으로만 하여 생성됩니다. 이와 같이 실행 시점에 들어오는 파라미터의 값들에 따라 구현되는 쿼리의 모양이 달라지는 쿼리를 동적쿼리라고 합니다.
Q) JPQL보다 QueryDSL의 사용이 권장되는 이유?
QueryDSL은 엔티티 클래스를 기반으로 하여 작성된 코드를 통해 쿼리를 생성하기 때문에 코드의 가독성을 높여주고 쿼리 자체의 오타나 문법은 줄일 수 있도록 돕습니다. 예를 들어 “SELECT MAX(b.sortNo) FROM BOARD b where b.category = [category]” 와 같은 쿼리는 JPQL에서 보통 아래와 같이 엔티티를 직접 참조하는 방식으로 사용되며
QueryDSL의 경우에는 위와 같은 코드를 아래와 같이 자바 코드를 이용하는 방식으로 작성됩니다.
JPQL과 QueryDSL이 구현된 방식을 보면 알 수 있듯이, JPQL의 경우 상대적으로 코드의 가독성이 떨어지고, 오타나 문법 오류 등을 찾기 어려우며, 컴파일 과정에서도 오타나 문법 오류를 걸러내지 못하여 런타임 즉 서버의 실행 과정에서 에러가 발생할 수 있습니다. 반면에 QueryDSL의 경우 도메인의 변경이 직접적으로 쿼리에 반영되고, ide가 코드 자동완성기능을 지원하여 주어 쿼리를 더욱 빠르고 안전하게 구현할 수 있도록 돕습니다. 특히나 QueryDSL을 사용한 경우에 컴파일 과정에서 쿼리에 문제가 있는 경우 이를 감지하기 때문에, 서버의 런타임 과정에서 문제가 발생할 가능성을 줄여줍니다. 더불어 가독성과 유지보수 측면에서도 QueryDSL이 JPQL 보다 많은 이점을 가지기 때문에 일반적으로 복잡한 쿼리나 동적쿼리의 구현이 필요한 경우에 JPQL보다는 QueryDSL의 사용이 권장됩니다.
QueryDSL 특징
QueryDSL은 엔티티로부터 생성된 Q클래스를 사용하여 쿼리를 구현함으로써 타입의 안정성을 보장합니다.
QueryDSL 기본 세팅
환경
- Java 17
- IntelliJ IDEA 2023.1
- gradle
1. build.gradle 파일에 디펜던시 및 설정 추가
build.gradle에 아래의 디펜던시를 추가하여 줍니다.
** 기본적으로 jpa 와 관련한 설정은 되어있다고 가정하였습니다. (jpa 기본 설정 관련 참고 : https://mihee0703.tistory.com/232)
// querydsl 관련 설정
// querydsl-jpa와 querydsl-core 반드시 필요
implementation ("com.querydsl:querydsl-jpa:${dependencyManagement.importedProperties['querydsl.version']}:jakarta")
implementation("com.querydsl:querydsl-core")
// querydsl 관련한 추가적인 기능을 제공하여 주는 라이브러리로 필수는 아님
// implementation("com.querydsl:querydsl-collections")
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
- implementation("com.querydsl:querydsl-core")
queryDSL의 핵심 모듈로, queryDSL을 사용하기 위한 가장 기본적인 기능을 제공하는 역할을 합니다.
- implementation ("com.querydsl:querydsl-jpa:[version]:jakarta")
gradle에서 사용되는 문법으로 적절한 버전의 값을 자동으로 설정하여 주는 기능을 제공합니다. 해당 디펜던시는 queryDSL JPA모듈의 의존성을 추가하는 역할을 합니다. 스프링부트 3.0 이후 버전인 경우에는 jakarta를 추가해주어야 합니다.
- annotationProcessor "com.querydsl:querydsl-apt:[version]:jakarta"
해당 모듈은 엔티티 클래스를 기반으로 하여 Q클래스를 생성하기 위하여 사용되는 라이브러리입니다.
- annotationProcessor "jakarta.annotation:jakarta.annotation-api"
jakarta에서 사용되는 annotation들을 처리해주기 위해 추가해준 것입니다.
- annotationProcessor "jakarta.persistence:jakarta.persistence-api"
ompileJava를 실시하면 java.lang.NoClassDefFoundError: jakarta/persistence/Entity 에러가 발생하는데 이를 해결하기 위해 추가하여 줍니다.
** ${dependencyManagement.importedProperties['querydsl.version']}
: gradle에서 사용되는 groovy 문법으로 dependencyManagement를 통해 querydsl의 version 값을 가져오는 것입니다. 기본적으로 dependencyManagement에 의해 기본적으로 버전을 관리하여 주는데, 버전 뒤에 추가적으로 jakarta나 jpa 등 추가적으로 붙은 것이 있는 경우에는 위와 같이 직접 버전 정보를 가져와서 설정해주어야 합니다.
build.gradle에 위와 같이 설정해준 후에 compileJava를 실행하면 src/main/generated 폴더가 생성되고 그 하위에 엔티티와 관련한 Q클래스 파일이 생성되는 것을 확인할 수 있습니다.
참고
//https://velog.io/@kimsundae/Gradle-SpringBoot-3.x-QueryDSL-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0
'JAVA' 카테고리의 다른 글
[ Java ] - 입출력 하기, 스트림 종류 및 예시 코드 (0) | 2023.10.30 |
---|---|
[ JAVA ] - 람다식이란? (0) | 2023.10.19 |
[ Java ] - 난수 생성 (0) | 2023.10.18 |
[ Java ] - 프로세스와 쓰레드 - 02) (0) | 2023.10.17 |
[ Java ] - 프로세스와 쓰레드 - 01) (0) | 2023.10.16 |