1. 동적 쿼리(Dynamic Query)란?
- 사용자가 입력한 조건에 따라 유연하게 쿼리를 생성하는 방식
- 예시: 이름만 입력할 경우 이름으로 검색, 이메일만 입력하면 이메일로 검색, 둘 다 입력하면 둘 다 조건으로 검색
- 동적 쿼리가 필요한 이유
- 기존 방식의 한계 : 조건이 조금만 바뀌어도 메서드가 늘어나거나, 코드가 중복되고 분기문이 늘어나 유지보수가 불가능함
2. BooleanBuilder, BooleanExpression
- 동적 쿼리를 작성할 때 사용하는 대표적인 방법, 역할과 사용 시점이 다름
BooleanBuilder란?
여러 조건을 동적으로 추가하거나 제거할 수 있는 "가변 조건 컨테이너"
➡️ 조건을 하나씩 쌓아가며 만드는 방식으로, 복잡한 검색 조건에 유용
BooleanBuilder builder = new BooleanBuilder();
if (username != null) {
builder.and(user.username.contains(username));
}
if (email != null) {
builder.and(user.email.contains(email));
}
if (role != null) {
builder.and(user.roleEnum.eq(role));
}
List<User> result = queryFactory
.selectFrom(user)
.where(builder)
.fetch();
| 항목 | 내용 |
|---|
| null 처리 | 직접 if문 작성 |
| 조립 방식 | .and(), .or()로 조건 누적 |
| 장점 | 조건을 순차적으로 추가/삭제 가능 |
| 단점 | 코드가 길어지고 재사용 어려움 |
BooleanExpression이란?
하나의 조건(표현식)을 메서드로 정의해 조합하는 불변 표현식
➡️ null 조건은 QueryDSL이 자동으로 무시하여 코드가 깔끔
private BooleanExpression usernameContains(String username) {
return username != null ? user.username.contains(username) : null;
}
private BooleanExpression emailContains(String email) {
return email != null ? user.email.contains(email) : null;
}
private BooleanExpression roleEq(UserRoleEnum role) {
return role != null ? user.roleEnum.eq(role) : null;
}
List<User> result = queryFactory
.selectFrom(user)
.where(
usernameContains(cond.getUsername()),
emailContains(cond.getEmail()),
roleEq(cond.getRole())
)
.fetch();
| 항목 | 내용 |
|---|
| null 처리 | 자동 무시 |
| 조립 방식 | 메서드 간 병합 (.and(), .or()) |
| 장점 | 코드 재사용성 높고 구조가 깔끔 |
| 단점 | builder처럼 즉석 추가는 불가 |
| 구분 | BooleanBuilder | BooleanExpression |
|---|
| 개념 | 조건을 모아두는 컨테이너 | 단일 조건의 표현식 |
| 객체 성격 | 가변(Mutable) | 불변(Immutable) |
| null 처리 | 직접 제어 | 자동 무시 |
| where 작성 방식 | .where(builder) | .where(조건1, 조건2, 조건3) |
| 재사용성 | 낮음 | 높음 |
| 코드 가독성 | 복잡함 | 깔끔함 |
- 사용해야 할 상황
- BooleanBuilder - 조건이 많고, 일부 조건을 동적으로 추가/삭제해야할 때(유연한 조건 추가 가능)
- BooleanExpression - 조건이 고정되어 있고, null만 무시하면 될 때(코드가 간결하고 재사용성 높음)