3. QueryDSL 소개 및 JPQL과 비교
(1) JPQL의 단점
- 오타나 문법 오류를 컴파일 시에 찾을 수 없음
-> 실행 전까지 오류 발견이 불가능
-> 개발 중 오류 발견이 어렵고, 실행 중 예외 발생
- 동적 쿼리 작성이 불편
-> if문이 많아질수록 가독성이 나빠짐
(2) QueryDSL의 장점
- 타입 안전성 보장
-> 컴파일 시점에 username이 String 타입인지 확인 가능
-> 오타가 있으면 바로 에러가 발생하여 실행 전에 오류를 방지
- 동적 쿼리 작성이 간편
-> BooleanBuilder를 사용해서 조건을 유동적으로 추가 가능
-> if문을 최소화하고 가독성을 높임
| JPQL | QueryDSL | |
| 문법 | 문자열 기반 | 코드 기반 |
| 타입 체크 | 런타임 오류 가능 | 컴파일 시 오류 잡힘 |
| 동적 쿼리 | 어렵고 복잡 | 유연하고 깔끔 |
| IDE 지원 | 거의 없음 | 자동완성 리팩토링 용이 |
(3) QueryDSL
- QueryDSL: JPA 위에서 동작하는 안전한 쿼리 작성 도구, Java 코드로 쿼리를 작성
-> 동적 쿼리에 강함, 문법 오류를 컴파일 타임에 체크, IDE에서 자동완성 가능
- 기본 사용 구조
QMember m = QMember.member;
queryFactory.selectFrom(m)
.where(m.age.gt(20))
.fetch(); // 실제 쿼리를 실행하고 결과를 리스트로 받아옴
-> Member 엔티티를 기반으로 만들어진 Q타입 객체를 사용
+) Q타입
- Q타입 : 엔티티 기반으로 QueryDSL이 자동 생성하는 쿼리 전용 클래스
- build/generated 폴더에 위치
-> 자동 완성 가능
-> 컴파일 오류로 오타/문법 실수 바로 잡힘
-> 리팩토링에 강함
(4) QueryDSL 실습
- Gradle 설정
def querydslVersion = "5.0.0"
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 querydslDir = "$buildDir/generated/sources/annotaionProcessor/java"
sourceSets {
main {
java {
srcDirs += querydslDir
}
}
}
tasks.withType(JavaCompile).configureEach {
options.annotationProcessorGeneratedSourcesDirectory = file(querydslDir)
}
clean {
delete file(querydslDir)
}
-> 계속 Q클래스가 뜨지 않아서 아예 디렉토리를 지정해두었다.
- QueryFactory 빈 등록
package com.week5.likelionmember.config;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QueryDslConfig {
@Bean
public JPAQueryFactory queryFactory(EntityManager em) {
return new JPAQueryFactory(em);
}
}
- MemberTest.java 수정
package com.week5.likelionmember;
import com.week5.likelionmember.domain.Member;
import com.week5.likelionmember.repository.MemberRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class MemberTest implements CommandLineRunner {
private final MemberRepository memberRepository;
public MemberTest(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Override
public void run(String... args) throws Exception {
// 쿼리 메서드 실행
List<Member> queryMethodResult = memberRepository.findByUsernameAndAgeGreaterThanEqual("yujin", 23)
System.out.println("쿼리 메소드 결과: ");
// @Query JPQL 실행
List<Member> jpqlResult = memberRepository.findUsernameAndOlderThan("yujin", 23);
System.out.println("@Query JPQL 결과:");
jpqlResult.forEach(System.out::println);
// QueryDSL 실행
QMember m = QMember.member;
List<Member> querydslResult = queryFactory.selectFrom(m)
.where(
m.age.goe(23),
m.university.eq("서울여자대학교")
)
.fetch();
}
}'멋쟁이사자처럼 13기 > 정기 세션' 카테고리의 다른 글
| [멋사/Mac OS] 5주차 정기 세션 (Part 4. 영속성 전이 ~ Part 6. Auditing) (0) | 2025.06.20 |
|---|---|
| [멋사/Mac OS] 5주차 정기 세션 (Part 2. JPA 쿼리 작성 방법) (0) | 2025.06.20 |
| [멋사/Mac OS] 5주차 정기 세션 (Part 1. 실습환경 세팅) (0) | 2025.06.20 |
| [멋사/Mac OS] 4주차 정기 세션 (Part 3. 실습) (0) | 2025.06.18 |
| [멋사/Mac OS] 4주차 정기 세션 (Part 2. 엔티티 설계) (0) | 2025.06.18 |