QueryDSL을 이용해서 다른 테이블과 조인을 하고 파라미터로 특정 값을 받아와 where 구문으로 필터링하여 결과를 조회하는 코드를 작성했다.
파라미터로 받아오는 userId, itemId가 모두 값이 있을 경우는 정상적으로 예약 리스트를 받아올수 있었지만, 둘 중 하나라도 값이 null이거나 둘 다 null이라면 예외를 출력하고 있다.
파라미터로 전달 받는 userId와 itemId가 null이므로 디폴트로 임의의 값을 넣어주면 괜찮지 않을까 생각했다.하지만 userId와 itemId를 임의로 넣어주게되면 다른 데이터를 불러오게 될 수도 있으니 null체크를 해서 예외처리를 해주고 다시 실행해보았다.
예약 목록을 조회할 수 없다고 예외를 출력해주고 있지만, 원래 구현하려 했던 기능은 파라미터가 없으면 필터링 없이 모든 목록이 조회되도록 하는 것이기 때문에 다른 방법을 찾아 보기로했다.
BooleanBuilder는 QueryDSL에서 동적 쿼리를 생성할 때 유용한 도구로, 여러 조건을 동적으로 추가하거나 제거할 수 있도록 해준다.
빈 상태로 생성 가능하며, 이후 조건을 추가하면서 AND 또는 OR로 결합할 수 있다.
조건이 null인 경우 해당 조건을 추가하지 않도록 쉽게 처리할 수 있고 복잡한 조건문을 깔끔하게 관리할 수 있다.
BooleanBuilder를 초기화 해주고 userId와 itemId가 null 값이 아닐 때만 비교하도록 하였다. 이렇게 코드를 작성하면 파라미터 중 1개가 null 값이면 null이 아닌 파라미터 값만 넣어서 필터링을 하고 둘 다 null 값일 때는 필터링 없이 모든 예약 목록을 조회해서 가져올 수 있다.
(BooleanBuilder를 사용하면 조건이 하나도 추가되지 않은 경우 where절이 비어있게 된다. 이 경우 QueryDSL은 where절을 생략하고, 필터링 없이 모든 데이터를 조회한다)
지금과 같은 경우를 해결할 수 있는 또 다른 방법으로 BooleanExpression을 활용할 수 있다.
BooleanExpression은 QueryDSL의 주요 조건 표현식 중 하나로, 단일 논리 조건을 표현하거나 다른 표현식과 결합할 수 있다. Predicate의 하위 타입으로, BooleanBuilder보다 구체적인 조건 작성에 사용된다.
// 기본 조건
BooleanExpression userCondition = userId != null ? reservation.user.id.eq(userId) : null;
BooleanExpression itemCondition = itemId != null ? reservation.item.id.eq(itemId) : null;
// 조건 결합
BooleanExpression finalCondition = userCondition != null && itemCondition != null
? userCondition.and(itemCondition)
: (userCondition != null ? userCondition : itemCondition);
// 동적 쿼리 적용
List<ReservationResponseDto> results = jpaQueryFactory
.select(Projections.constructor(
ReservationResponseDto.class,
reservation.id,
reservation.user.nickname,
reservation.item.name,
reservation.status,
reservation.startAt,
reservation.endAt
))
.from(reservation)
.join(reservation.user, user)
.join(reservation.item, item)
.where(finalCondition) // 결합된 조건 사용
.fetch();
모든 케이스에 정상적으로 데이터가 조회되는 모습을 확인할 수 있다.