CS/웹개발
QueryDSL
hyunji1109
2025. 4. 6. 21:07
✅ QueryDSL
Java 기반의 타입 안전한 SQL/JPQL 빌더 라이브러리
복잡한 쿼리를 자바 코드로 작성할 수 있도록 도와주는 도구
JPA로 복잡한 쿼리를 작성할 때는 보통 JPQL이나 @Query를 사용 ->
이 방식은 문자열 기반이기 때문에 컴파일 시점에 문법 오류를 잡아주지 못하고 가독성도 떨어짐 ->
QueryDSL은 이를 해결하기 위해 Java 코드로 SQL을 작성
✅ 장점
- 타입 안전성
- 쿼리를 Java 코드로 작성하므로 컴파일 시점에 오류를 잡을 수 있다.
- 자동 완성
- IDE의 자동 완성 기능을 사용할 수 있어 생산성이 높다.
- 복잡한 동적 쿼리 작성
- 조건문과 결합하여 동적으로 쿼리를 쉽게 만들 수 있다.
- 재사용성
- Query 객체를 재활용하기 쉽다.
- 가독성
- JPQL보다 훨씬 명확하고 직관적인 쿼리 작성 가능
✅ QueryDSL 설정
1) build.gradle
plugins {
id 'java'
id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10'
}
dependencies {
implementation 'com.querydsl:querydsl-jpa'
annotationProcessor 'com.querydsl:querydsl-apt'
annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
annotationProcessor 'jakarta.annotation:jakarta.annotation-api'
}
// QueryDSL Q 클래스 생성 경로 설정
def querydslDir = "$buildDir/generated/querydsl"
sourceSets {
main.java.srcDirs += querydslDir
}
2) 엔티티
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String username;
private int age;
@ManyToOne(fetch = FetchType.LAZY)
private Team team;
}
📌 Q도메인 클래스가 생성되기 위해서는 엔티티 클래스에 @Entity가 붙어 있어야 함
3) QMember
// EntityManager를 통해 JPAQueryFactory 생성
JPAQueryFactory queryFactory = new JPAQueryFactory(em);
QMember m = QMember.member;
Member result = queryFactory
.selectFrom(m)
.where(m.username.eq("현지"))
.fetchOne();
- selectFrom
- select + from
- where
- 조건
- eq()
- equals
- fetchOne()
- 단일 결과
- fetch()
- 리스트 결과
- fetchFirst()
- limit 1
- fetchCount()
- count 쿼리
4) MemberRepositoryImpl
@Repository
public class MemberQueryRepository {
private final JPAQueryFactory queryFactory;
public MemberQueryRepository(EntityManager em) {
this.queryFactory = new JPAQueryFactory(em);
}
public List<Member> search(String usernameCond, Integer ageCond) {
return queryFactory
.selectFrom(member)
.where(
usernameEq(usernameCond),
ageEq(ageCond)
)
.fetch();
}
private BooleanExpression usernameEq(String usernameCond) {
return StringUtils.hasText(usernameCond) ? member.username.eq(usernameCond) : null;
}
private BooleanExpression ageEq(Integer ageCond) {
return ageCond != null ? member.age.eq(ageCond) : null;
}
}
✅ Q클래스
QueryDSL이 @Entity 클래스 기반으로 자동 생성하는 메타 모델 클래스
@Entity
public class Member {
@Id
private Long id;
private String username;
private int age;
}
👉 생성시 자동으로 QMember.java 클래스가 만들어 진다.
public class QMember extends EntityPathBase<Member> {
public static final QMember member = new QMember("member");
public final StringPath username = createString("username");
public final NumberPath<Integer> age = createNumber("age", Integer.class);
public final NumberPath<Long> id = createNumber("id", Long.class);
}
👉 Q클래스 사용하기
QMember member = QMember.member;
Member result = queryFactory
.selectFrom(member)
.where(member.username.eq("현지")) //eq를 사용
.fetchOne();