QueryDSL이란?
•
하이버네이트 쿼리 언어의 쿼리를 타입에 안전하게 생성 및 관리해주는 프레임워크
•
정적 타입을 이용하여 SQL과 같은 쿼리를 생성할 수 있게 해준다.
•
Spring Data JPA를 사용하여 복잡한 쿼리 혹은 동적 쿼리를 구현하는데 한계가 있는데 이런 문제점을 해결할 수 있는 것이 QueryDSL이다.
QueryDSL이 등장하기 이전에는 Mybatis, JPQL, Criteria 등 문자열 형태로 쿼리문을 작성하여 컴파일 시에 오류를 발견하는 것이 불가능했다.
하지만 QueryDSL은 자바 코드로 SQL 문을 작성할 수 있어 컴파일 시에 오류가 발생하여 잘못된 쿼리가 실행되는 것을 방지할 수 있다.
QueryDSL의 장점
•
문자가 아닌 코드로 쿼리를 작성할 수 있어 컴파일 시에 에러를 확인할 수 있다.
•
IDE의 자동 완성 기능의 도움을 받을 수 있다.
•
복잡한 쿼리나 동적 쿼리 작성이 편리하다.
•
쿼리 작성 시 제약 조건 등을 메서드 추출을 통해 재사용 할 수 있다.
•
JPQL 문법과 유사한 형태로 작성할 수 있어 쉽게 적응할 수 있다.
설정
SpringBoot3.x + QueryDSL 5.0.0
•
build.gradle
설정을 아래와 같이 설정해준다.
◦
dependencies 설정 추가
◦
Q클래스가 생성될 경로 지정
▪
따로 경로를 설정해주는 이유?
•
빌드 디렉토리에 생성되면 이 디렉토리를 직접 소스셋에 추가해야함
◦
소스셋? :
소스셋(Source Set)이란 Gradle이 프로젝트 빌드를 진행할 때 참조하는 소스 코드와 리소스 파일들의 집합을 의미합니다.
예를 들어, Java 프로젝트에서는 'main'과 'test'라는 두 가지 기본 소스셋을 가지게 됩니다. 'main' 소스셋은 애플리케이션의 주요 소스 코드와 리소스들을 담고 있고, 'test' 소스셋은 테스트를 위한 소스 코드와 리소스들을 담고 있습니다.
각 소스셋은 소스 코드가 위치한 디렉토리와 그에 대응하는 컴파일된 클래스 파일들이 저장될 위치를 정의합니다. 이를 통해 Gradle은 프로젝트의 빌드 과정을 관리하게 됩니다.
따라서, Q 클래스의 생성 위치를 소스셋에 포함된 디렉토리로 설정해두면, 빌드 시에 자동으로 Q 클래스를 인식하고 컴파일할 수 있게 됩니다. 이는 추가적으로 소스셋을 설정해주는 작업을 줄여주므로 편리합니다.
•
빌드 디렉토리는 프로젝트 빌드 시 생성되는 중간 파일들이 저장되는 곳. 이 디렉토리의 내용은 clean작업 등으로 쉽게 삭제될 수 있음
•
팀원들이 Q클래스 파일을 더 쉽게 찾을 수 있음. 코드 관리 용이
•
config
◦
프로젝트 전역에서 QueryDSL을 사용할 수 있도록 JPAQueryFactory를 Bean으로 등록해준다.
▪
JPAQueryFactory의 역할?
Querydsl을 사용하여 쿼리를 생성하고 실행하는 데 필요한 메서드를 제공하는 클래스. 빈으로 등록하면 어디서든 주입받아 사용할 수 있다.
Q클래스
•
JPAAnnotationProcessor가 컴파일 시점에 @Entity 어노테이션이 선언된 클래스에 대해 미리 생성하는 쿼리 객체
•
해당 객체에 쿼리문을 메서드 형태로 호출하여 SQL문을 짜듯이 코드로 쿼리문 작성이 가능하다.
•
도메인 클래스의 각 필드를 프로퍼티를 가지고 있으며 이 프로퍼티들은 쿼리 작성 시 사용된다.
사용
•
커스텀 인터페이스에 메서드 정의
•
커스텀 인터페이스를 구현하는 클래스에 QueryDSL 쿼리를 작
•
JpaRepository를 상속하는 Repository가 커스텀 인터페이스를 상속하도록 설정
◦
구현클래스에 작성된 QueryDSL코드를 Repository가 사용할 수 있게 됨
BooleanExpression - 동적 조회
•
BooleanExpression은 QueryDSL에서 제공하는 클래스
•
SQL 또는 JPQL 쿼리에서 WHERE절에 해당하는 조건식을 표현하는데 사용됨
◦
BooleanExpression은 null을 리턴할 경우 해당 조건문은 Where에서 제거된다.
◦
null이 반환되면 조건이 제거되고 아니면 자동으로 조건이 적용된다는 기능을 통해 명시적인 쿼리문 작성이 가능하다.
BooleanBuilder 도 있는데?
◦
동적쿼리를 작성할 때 사용하는 또다른 클래스
◦
Booleanbuilder를 사용하여 이름과 나이로 멤버를 찾아주는 메서드 예제
public List<Member> findMembers(String name, Integer age) {
BooleanBuilder builder = new BooleanBuilder();
if (!StringUtils.isEmpty(name)) {
builder.and(QMember.member.name.eq(name));
}
if (age != null) {
builder.and(QMember.member.age.eq(age));
}
return jpaQueryFactory
.select(QMember.member)
.from(QMember.member)
.where(builder)
.fetch();
}
Java
복사
◦
위 코드처럼 if문으로 조건을 비교해서 BooleanBuilder객체에 값을 넣어주고 이 객체를 WHERE절에 넘겨주면 조건문이 완성된다.
◦
하지만 반복적인 if문은 코드를 지저분하게 만들고 테이블의 필드 수가 많다면 if문은 더 늘어날 것.
이러한 이유 때문에 BooleanBuilder보다는 BooleanExpression 사용이 권장된다.
OrderSpecifier - 동적 정렬
•
QueryDSL에서 제공하는 클래스로, 쿼리 결과의 정렬 순서를 명시하는 데 사용된다.
•
SQL쿼리의 ORDER BY 절에 해당하는 기능을 수행한다.
•
정렬 방식은 asc 또는 desc를 사용하고, 정렬 대상 필드는 Q클래스의 프로퍼티를 사용한다.