📍Query DSL ?
DSL:특정 도메인에서 발생하는 문제를 효과적으로 해결하기 위해 설계된 언어.
Query DSL : DSL 언어를 제공해주는 라이브러리.
즉, 쿼리를 타입 안전하게 자바 문법으로 작성, 메서드 체이닝으로 가독성 상향, 단순하고 간결함을 위해서 사용한다.
📍타입이 왜 안전할까?
- @Entity가 붙은 클래스에 맞춰서 QClass가 컴파일 타임에 자동으로 생성된다.
@Entity
public class User {
@Id
private Long id;
private String name;
private Integer age;
}
public class QUser extends EntityPathBase<User> {
public final StringPath name = createString("name");
public final NumberPath<Integer> age = createNumber("age", Integer.class);
public final NumberPath<Long> id = createNumber("id", Long.class);
}
각 필드가 정확한 타입(StringPath, NumberPath)으로 정의되어 있어 잘못된 타입의 연산을 작성하면 컴파일 에러가 발생하게 된다.
- NumberExpression과 StringExpression을 통해서 다양한 메서드가 정의되어 있으며, 우리가 만약 타입이 다른 연산을 실행하면 컴파일 타임에 오류가 발생하며 타입 안정성이 유지된다.
BooleanExpression isAdult = user.age.gt(18);
BooleanExpression startsWithJ = user.name.startsWith("J");
이렇게 메서드가 QClass 안에 구현되어 있어서 기존 자바와 같이 문법 오류를 잡아낼 수 있다.
📍중복 조건식 재사용
- JPQL 쿼리는 문자열이기 때문에 조건을 캡슐화하거나 재사용하기 어렵다.
- QueryDSL은 조건 표현(Expression 영역)과 JPQL 생성/실행 영역을 분리하므로, 조건을 메서드로 캡슐화하여 재사용할 수 있다.
// 조건식 캡슐화 (Expression 영역)
private BooleanExpression isActive() {
return QUser.user.status.eq("ACTIVE");
}
private BooleanExpression isOlderThan(int age) {
return QUser.user.age.gt(age);
}
// JPQL 생성 및 실행 (JPAQueryFactory)
List<User> users = queryFactory.selectFrom(QUser.user)
.where(isActive().and(isOlderThan(18))) // 조건 재사용
.fetch();
// 다른 쿼리에서도 재사용 가능
long userCount = queryFactory.selectFrom(QUser.user)
.where(isActive().and(isOlderThan(30))) // 동일 조건 사용
.fetchCount();
위 예시는 짧은 비교 쿼리문이지만, 복잡한 쿼리를 메서드화하게 된다면 더욱 효율적으로 코드를 구현할 수 있게 된다.
📍깔끔한 동적 쿼리 작성
public List<User> searchUsers(String name, Integer age, String status) {
BooleanBuilder builder = new BooleanBuilder();
if (name != null && !name.isEmpty()) {
builder.and(QUser.user.name.contains(name));
}
if (age != null) {
builder.and(QUser.user.age.gt(age));
}
if (status != null && !status.isEmpty()) {
builder.and(QUser.user.status.eq(status));
}
return queryFactory.selectFrom(QUser.user)
.where(builder)
.fetch();
}
복잡한 조건일수록 문자열 조합이 혼란스러울 수 있는 SQL에 반해, DSL은 상대적으로 깔끔하게 동적쿼리 관리가 가능하다.
'springboot' 카테고리의 다른 글
[SpringBoot] 영속성 컨텍스트, 그리고 EntityManager (0) | 2025.01.09 |
---|---|
[SpringBoot] 끄적끄적 프로젝트 쿼리 성능 개선을 해보자 (0) | 2025.01.06 |
[SpringBoot] 웹소켓으로 채팅하고 채팅방 관리하기 (0) | 2024.11.23 |
[SpringBoot] Session을 활용한 회원가입/로그인 유지 (1) | 2024.11.01 |
[SpringBoot] Spring Boot로 REST API 만들기 (0) | 2024.09.28 |