QueryDSL을 사용하다 보면 Predicate
와 BooleanExpression
두 가지 타입을 자주 마주치게 됩니다. 둘 다 쿼리의 조건을 표현하는 데 사용되지만, 사용 목적과 특징이 조금 다릅니다. 이번 TIL에서는 이 두 타입의 차이를 정리하고, 언제 어떤 것을 사용해야 하는지 예제를 통해 알아보겠습니다.
Predicate
는 QueryDSL에서 조건을 표현하는 가장 일반적인 인터페이스입니다. QueryDSL의 다양한 조건 표현식을 처리할 수 있는 범용적인 타입입니다.
and
, or
) 같은 고급 기능은 제공하지 않습니다.BooleanExpression
은 Predicate
의 구체적인 구현체입니다. QueryDSL에서 Boolean 타입의 조건을 명확하게 표현하고, 조건 조합을 쉽게 할 수 있는 추가 메서드를 제공합니다.
and
, or
, not
등 조건을 결합할 수 있는 메서드를 제공합니다.Predicate는 단순 조건을 전달하거나, QueryDSL API에서 기본 조건 타입으로 사용됩니다.
private Predicate titleContains(String keyword) {
return keyword != null ? QTodo.todo.title.contains(keyword) : null;
}
// 사용 예시
Predicate condition = titleContains("project");
List<Todo> todos = queryFactory
.selectFrom(QTodo.todo)
.where(condition) // 단일 조건 사용
.fetch();
BooleanExpression은 조건 조합과 동적 조건 생성을 지원합니다.
private BooleanExpression titleContains(String keyword) {
return keyword != null ? QTodo.todo.title.contains(keyword) : null;
}
private BooleanExpression createdDateBetween(LocalDateTime startDate, LocalDateTime endDate) {
return startDate != null && endDate != null
? QTodo.todo.createdAt.between(startDate, endDate)
: null;
}
// 사용 예시
BooleanExpression condition = titleContains("project")
.and(createdDateBetween(LocalDateTime.now().minusDays(7), LocalDateTime.now()));
List<Todo> todos = queryFactory
.selectFrom(QTodo.todo)
.where(condition) // 복합 조건 사용
.fetch();
Predicate는 간단한 단일 조건을 전달하는 데 적합합니다.
private Predicate titleContains(String keyword) {
return keyword != null ? QTodo.todo.title.contains(keyword) : null;
}
// 단순 조건 전달
Predicate condition = titleContains("meeting");
List<Todo> todos = queryFactory
.selectFrom(QTodo.todo)
.where(condition)
.fetch();
BooleanExpression은 and
, or
메서드를 통해 여러 조건을 결합할 때 유리합니다.
private BooleanExpression titleContains(String keyword) {
return keyword != null ? QTodo.todo.title.contains(keyword) : null;
}
private BooleanExpression createdDateBetween(LocalDateTime startDate, LocalDateTime endDate) {
return startDate != null && endDate != null
? QTodo.todo.createdAt.between(startDate, endDate)
: null;
}
// 복합 조건
BooleanExpression condition = titleContains("meeting")
.and(createdDateBetween(LocalDateTime.now().minusDays(30), LocalDateTime.now()));
List<Todo> todos = queryFactory
.selectFrom(QTodo.todo)
.where(condition)
.fetch();
상황 | Predicate | BooleanExpression |
---|---|---|
단일 조건 사용 | 적합 | 가능 |
복잡한 조건 조합 | 부적합 | 적합 |
조건을 동적으로 추가해야 할 때 | 제한적 | 적합 |
QueryDSL API에서 기본 조건 전달 | 적합 | 가능 |
and , or , not 같은 조건 조합 | 불가능 | 가능 |
Predicate:
BooleanExpression:
이번에 Predicate와 BooleanExpression의 차이를 정리하면서, 상황에 맞게 적절한 타입을 선택하는 것이 중요하다는 것을 다시 느꼈습니다. 실무에서는 대부분 복잡한 조건 조합이 필요하기 때문에 BooleanExpression을 사용하는 경우가 더 많을 것 같습니다. 하지만 간단한 조건만 필요한 경우에는 Predicate를 사용해 코드의 간결함을 유지할 수 있겠죠.