queryDSL에 대해 더 자세히 알고 싶다면, 1편을 보고오시는것을 추천드립니다!
2023.11.03 - [분류 전체보기] - queryDSL이란? 간단한 설명과 사용이유
queryDSL이란? 간단한 설명과 사용이유
👉 글을 쓰게 된 이유 저는 JPA가 복잡한 쿼리를 효율적이고 편리한 개발을 지원하지만 특히 복잡한 쿼리를 작성할 때 일부 단점이 있다고 생각했습니다. JPA는 기본적으로 단순한 CRUD 쿼리와 간
sean-lets-go.tistory.com
👉 Gradle 의존성과 세팅
plugins {
id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10' // Q 클래스 생성 플러그인
// ...
}
def querydslDir = "$buildDir/generated/querydsl" // 생성된 Q 클래스가 저장될 위치를 정의한다.
// queryDSL 자체에 대한 config
querydsl {
jpa = true // jpa = true로 설정하여 JPA 애너테이션을 인식
querydslSourcesDir = querydslDir // querydslSourcesDir를 querydslDir로 설정하여 Q 클래스에 대한 output 디렉토리를 지정
}
sourceSets {
main.java.srcDir querydslDir // Q 클래스 등이 저장되는 querydslDir를 소스 코드가 저장되는 디렉토리로 등록
// 이 덕에 Gradle이 자동으로 QueryDSL 코드를 컴파일할 수 있다.
}
configurations {
querydsl.extendsFrom compileClasspath // querydsl 클래스 경로를 컴파일 클래스 경로에 상속
}
// 내부적으로 Querydsl은 Java의 Annotation Processor를 이용한다.
// 컴파일러는 이 경로에 위치한 모든 JAR 파일들을 검색하여 annotation processor를 찾는다.
// 그리고 이를 실행하여 소스 코드에서 정의한 어노테이션들을 처리한다.
compileQuerydsl {
options.annotationProcessorPath = configurations.querydsl
}
dependencies {
//...
implementation "com.querydsl:querydsl-codegen:5.0.0" // QueryDSL 코드 생성
implementation "com.querydsl:querydsl-jpa:5.0.0" // JPA 지원
implementation "com.querydsl:querydsl-apt:5.0.0" // Annotation Process Tool
//...
}
// -proc:only: 이 옵션은 컴파일러의 어노테이션 처리만 수행하고, 클래스를 실제로 컴파일하지 않는 것을 의미한다.
// -processor: 이 옵션은 어노테이션 프로세서를 지정하는데, QueryDSL의 어노테이션 프로세서와 Lombok의 어노테이션 프로세서를 지정하여 명시적으로 설정한다.
project.afterEvaluate {
project.tasks.compileQuerydsl.options.compilerArgs = [
"-proc:only",
"-processor", project.querydsl.processors() +
',lombok.launch.AnnotationProcessorHider$AnnotationProcessor'
]
}
// Java 컴파일 작업이 compileQuerydsl 작업에 의존하도록 설정한다.
// compileQuerydsl 작업이 먼저 수행된 후에 compileJava 작업이 수행되게끔 순서를 정해주는 것인데,
// QueryDSL Q-Type 소스 생성 작업이 Java 컴파일 작업 전에 먼저 이뤄지도록 한다.
// 위 afterEvaluate와 같이 사용하면, Lombok 어노테이션 프로세스와 충돌하지 않는다.
tasks.named('compileJava') {
dependsOn tasks.named('compileQuerydsl')
}
👉 Repository
- 우리는 JpaRepository의 메서드(save, find)를 사용하면서 동시에 Custom(우리가 만들 메소드)한 QueryDSL을 사용해야 합니다.
- 그러기 위해선 다소 헷갈릴 수도 있지만, 관계를 잘 설정해주어야 합니다.
- 스프링은 JpaRepository 인터페이스를 상속받는 Repository 인터페이스를 찾으면, 이를 구현하는 프록시 객체를 생성합니다.
- Spring Data JPA는 인터페이스에 대한 프록시 객체를 생성할 때 해당 인터페이스와 그것이 상속하는 인터페이스의 모든 기능을 포함합니다.
- 밑의 코드를 보면, 스프링은 JpaRepository를 상속받은 -> ContractRepository의 구현 프록시 객체를 만들겁니다. 이때에 Jpa 기본 CRUD 기능 뿐만 아니라, 같이 상속받은 'ContractRepositoryCustom'의 기능도 포함해서 프록시 객체를 만들것입니다.
public interface ContractRepository extends JpaRepository<Contract, Long>, ContractRepositoryCustom {}
👉 성공!
👉 JPQL -> queryDSL
- 이러한 장점으로 인해 JPQL을 queryDSL로 변경했습니다.
- 문자가 아닌 코드로 쿼리를 작성할 수 있어 컴파일 시점에 문법 오류를 확인할 수 있습니다.
- 인텔리제이와 같은 IDE의 자동 완성 기능의 도움을 받을 수 있습니다.
- 복잡한 쿼리나 동적 쿼리 작성이 편리합니다.
- 쿼리 작성 시 제약 조건 등을 메서드 추출을 통해 재사용할 수 있습니다 .
- JPQL 문법과 유사한 형태로 작성할 수 있어 쉽게 적응할 수 있습니다 .
- 많이 복잡한 쿼리가 아니였는데도, IDE의 도움을 받을 수도 있고 직관적으로 변한것 같아 만족합니다.
👉 각 속도 비교
- 속도만 보면, queryDSL을 사용한것이 제일 느립니다...
- 제가 설정을 잘못한것일 수도 있겠습니다.
queryDSL의 성능이슈는 시간이되면 다시한번 다뤄보겠습니다!
이제는 .. JPA에서 복잡한 쿼리도 문제 없습니다!!
'Web Programming > JPA' 카테고리의 다른 글
ORM과 JPA, 구현체들의 관계 (1) | 2024.03.18 |
---|---|
queryDSL이란? 간단한 설명과 사용이유 (0) | 2023.11.03 |
nativeQuery을 제거해보자, 이유 + 성능체크 (0) | 2023.11.02 |