카테고리 없음

QueryDsl booleanExpression and메소드 체이닝 시 에러

se0nghyun2 2023. 6. 4. 16:01

도서 상세 조회 시 여러 조건들을 조합하여 검색할 수 있습니다.

1. 제목

2. 저자명

3. isbn

4. 출판일자 시작일자와 종료일자

 

상세조회 시,

제목이 있으면 조회조건으로 사용, 없으면 패스

저자명이 있으면 조회조건으로 사용, 없으면 패스

하는 식으로 생각하고 구현하였습니다.

 

 

문제발생

테스트 도중 아래와 같은 에러를 마주쳤습니다.

java.lang.NullPointerException: Cannot invoke "com.querydsl.core.types.dsl.BooleanExpression.and(com.querydsl.core.types.Predicate)" because the return value of "com.rebuild.book.domain.BookCustomRepositoryImpl.containTitle(String)" is null

 

 

기존구현

BookCustomRepositoryImpl

public PaginationRes findBooksByDetailConditions(FindBookDetailReqServiceDto findBookDetailReqServiceDto) {
                JPAQuery<FindBooksByDetailConditionsRes> query = queryFactory.select(Projections.fields(
                        FindBooksByDetailConditionsRes.class,book.bookId
                        ,book.title
                        ,book.author
                        ,book.publisher
                        ,book.bookState.as("state")
                        ,book.dt_pub
                         )
                        )
                        .from(book)
                    .where(detailConditions(findBookDetailReqServiceDto)) //이부분!!!!
                    .orderBy(getOrder(findBookDetailReqServiceDto.getSort()).desc())
                    .offset(Long.parseLong(findBookDetailReqServiceDto.getPage())-1)
                    .limit(Long.parseLong(findBookDetailReqServiceDto.getSize()))
                     ;
                List<FindBooksByDetailConditionsRes> list = query.fetch();
                Long totalCount = query.fetchCount();
                return new PaginationRes(list,totalCount);
    }

 

detailConditions메소드

  private BooleanExpression detailConditions(FindBookDetailReqServiceDto dto){
        return containTitle(dto.getTitle()). //이부분!!!
                and(containAuthor(dto.getAuthor())).
                and(containIsbn(dto.getIsbn())).
                and(containPub(dto.getPub())).
                and(containDate(dto.getStartDate(),dto.getEndDate()));
    }

    private BooleanExpression containTitle(String title){
        return  (title==null || title.isEmpty())? null : book.title.contains(title);
    }

	...위와 동일

and 파라미터를 호출할 수 없는데 그 이유는 containTitle의 리턴값이 null 이기 때문입니다.

즉, and메소드는 null을 리턴하는 BooleanExpresstion타입의 메소드에선 사용이 불가한 것으로 확인됩니다.

 

 

개선 ( BooleanExpression-> BooleanBuilder로 변경)

BookCustomRepositoryImpl

기존 그대로

 

detailConditions메소드

private BooleanBuilder detailConditions(FindBookDetailReqServiceDto dto){
    return containAuthor(dto.getAuthor()).
            and(containTitle(dto.getTitle())).
            and(containIsbn(dto.getIsbn())).
            and(containPub(dto.getPub())).
            and(containDate(dto.getStartDate(),dto.getEndDate()));
}

private BooleanBuilder containTitle(String title){
    return StringUtils.hasText(title) ? new BooleanBuilder(book.title.contains(title)) : new BooleanBuilder();

}

private BooleanBuilder containAuthor(String author){
    return StringUtils.hasText(author) ? new BooleanBuilder(book.author.contains(author)) : new BooleanBuilder();

}
private BooleanBuilder containPub(String pub){
    return StringUtils.hasText(pub) ? new BooleanBuilder(book.publisher.contains(pub)) : new BooleanBuilder();
}
private BooleanBuilder containIsbn(String isbn){
    return StringUtils.hasText(isbn) ? new BooleanBuilder(book.isbn.contains(isbn)) : new BooleanBuilder();
}

private BooleanBuilder containDate(String startDate, String endDate){
    return (StringUtils.hasText(startDate) && StringUtils.hasText(endDate))  ? new BooleanBuilder(book.dt_pub.between(startDate,endDate)) : new BooleanBuilder();
}

 


참고)

inflearn.com/questions/94056/강사님-where-다중-파라미터를-이용한-동적-쿼리-사용에-대한-질문입니다