Overivew
- QueryDSL을 활용하여, 검색기능을 구현하고 테스트하던중 이상현상을 확인하고, 대처 할 수 있다
전체코드
package com.sparta.doguin.domain.outsourcing.repository;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.sparta.doguin.domain.outsourcing.entity.Outsourcing;
import com.sparta.doguin.domain.outsourcing.entity.QOutsourcing;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
@Slf4j
@RequiredArgsConstructor
public class OutsourcingRepositoryQueryImpl implements OutsourcingRepositoryQuery {
private final JPAQueryFactory q;
private final BooleanBuilder b;
QOutsourcing qOutsourcing = QOutsourcing.outsourcing;
@Override
public Page<Outsourcing> search(String title, String content, String nickname, Pageable pageable) {
log.info("title {}", title);
log.info("content {}", content);
log.info("nickname {}", nickname);
if (title != null && !title.trim().isEmpty()) {
b.and(qOutsourcing.title.contains(title));
}
if (content != null && !content.trim().isEmpty()) {
b.and(qOutsourcing.content.contains(content));
}
if (nickname != null && !nickname.trim().isEmpty()) {
b.and(qOutsourcing.user.nickname.contains(nickname));
}
List<Outsourcing> outsourcingList = q
.select(
Projections.constructor(
Outsourcing.class,
qOutsourcing.id,
qOutsourcing.user,
qOutsourcing.title,
qOutsourcing.content,
qOutsourcing.preferential,
qOutsourcing.work_type,
qOutsourcing.price,
qOutsourcing.recruit_start_date,
qOutsourcing.recruit_end_date,
qOutsourcing.work_start_date,
qOutsourcing.work_end_date,
qOutsourcing.area
)
)
.distinct()
.from(qOutsourcing)
.where(b)
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
return new PageImpl<>(outsourcingList, pageable, outsourcingList.size());
}
}
무엇이 이상한가?
- 클라이언트로부터 동일한 요청에 대해 여러번 검색 요청을 해보면 아래와같이 계속 로그에 표기된다
첫번째 검색
from
outsourcing o1_0
join
users u1_0
on u1_0.id=o1_0.user_id
where
o1_0.title like ? escape '!'
limit
?, ?
두번째 검색
from
outsourcing o1_0
join
users u1_0
on u1_0.id=o1_0.user_id
where
o1_0.title like ? escape '!'
and o1_0.title like ? escape '!'
limit
?, ?
세번째 검색
from
outsourcing o1_0
join
users u1_0
on u1_0.id=o1_0.user_id
where
o1_0.title like ? escape '!'
and o1_0.title like ? escape '!'
and o1_0.title like ? escape '!'
limit
?, ?
원인이 뭐지?
- 난 분명 title 하나의 조건에 대해서만 검색을 하고있는데 계속 title의 검색조건이 쌓이는 모습이다
- 저러면 저 3가지의 조건이 모두 일치하는 title에 대해서만 검색이 되기 떄문에 내가 원하는 방향이 아니다
해결방법
- 검색기능을 구현하기위해, 동적쿼리를 해결 할 수 있는 BooleanBuilder와 같이 문제를 해결하려고 하는것은 좋았지만, 이를 Config에서 한번만 초기화 시킨 상태로 IoC에 넣으니 검색 요청을 할때마다 BooleanBuilder가 초기화되지 않아 발생되었던 문제다
- 따라서 Config에서 Bean주입을 해주던 BooleanBuilder를 없애고 매요청마다 새로 생성하기위해 new로 만들어주었다
Config 삭제

new 생성자로 만들어주기
BooleanBuilder b = new BooleanBuilder();
문제해결 !