JPA

JPA , QueryDsl 수정 중 에러 해결

쭈녁 2024. 3. 17. 21:59

 

 

동적 쿼리에 대한 기능을 수정이 필요하여 JPA와 QueryDsl의 코드를 일부 수정했다.

 

수정하던 중 발생한 Exception들을 정리하여 보았다.

 

@Query 메서드를 통해 작성되어 있던 코드에서 에러가 발생하였다.

 

JPQL 코드

@Query(value = "select " +
        "d " +
        "from Deposit d " +
        "join ProjectMember pm on d.projectMember = pm " +
        "join Member m on pm.member = m " +
        "join User u on m.user = u " +
        "join Project p on pm.project = p " +
        "where d.status in (:statusList) " +
        "and d.createdDate >= :startDate and d.createdDate <= :endDate " +
        "and p.name like %:word1% " +
        "and u.username like %:word2% " +
        "and m.nickname like %:word3% " +
        "and u.name like %:word4% " +
        "order by d.status asc, d.createdDate asc ")
    Page<Deposit> findAllByDateRefundJPQL(@Param("statusList") List<Integer> statusList, LocalDateTime startDate, LocalDateTime endDate, @Param("word1") String word1, @Param("word2") String word2, @Param("word3") String word3, @Param("word4") String word4, Pageable pageable);

 

실행 시 UnsatisfiedDependencyException 예외가 발생하였다. 

에러 내용은 아래와 같았다.

Reason: Either use @Param on all parameters except Pageable and Sort typed once, or none at all

 

 

이유로는 pagenation에 해당하는 정보를 제외하고는 모든 파라미터에 @Param 어노테이션을 모두 쓰거나 모두 쓰지 않아야 한다는 내용이었다.

 

코드를 아래와 같이 모든 파라미터에 어노테이션을 적용하여 정상화할 수 있었다.

Page<Deposit> findAllByDateRefundJPQL(@Param("statusList") List<Integer> statusList, @Param("startDate")LocalDateTime startDate, @Param("endDate")LocalDateTime endDate, @Param("word1") String word1, @Param("word2") String word2, @Param("word3") String word3, @Param("word4") String word4, Pageable pageable);

 

QueryDsl 기존 코드

private BooleanExpression nameLike(String name) {
        if (StringUtils.hasText(name)) {
            return project.name.like("%" + name + "%");
        }
        return null;
    }

    private BooleanExpression contentLike(String content) {
        if (StringUtils.hasText(content)) {
            return project.name.like("%" + content + "%");
        }
        return null;
    }

    private BooleanExpression statusSame(Integer status) {
        if (status != null) {
            return project.status.eq(status);
        }
        return null;
    }

    private BooleanExpression projectPositionSame(List<Integer> positionCode) {
        if (positionCode != null && !positionCode.isEmpty()) {
            return projectPosition.codeGroup.id.in(positionCode);
        }
        return null;
    }

    private BooleanExpression projectSkillMatch(List<Integer> skillCode) {
        if (skillCode != null && !skillCode.isEmpty()) {
            return projectSkill.skill.id.in(skillCode);
        }
        return null;
    }

 

처음엔 아래와 같이 적용하였었다.

private BooleanBuilder multiCondition(ProjectSearchCond cond) {
    // 모든 값이 안들어오면 리스트 및 키워드에 대한 검색을 실행하지 않음
    if (cond.getSkillCode().isEmpty() && cond.getPositionCode().isEmpty() && !StringUtils.hasText(cond.getKeyword())) {
        return new BooleanBuilder().and(statusSame(cond.getStatus()));
    }
    // 하나라도 들어오면 or 조건으로 검색
    return new BooleanBuilder().and(statusSame(cond.getStatus()))
            .or((projectSkillMatch(cond.getSkillCode()))
                    .or(projectPositionSame(cond.getPositionCode()))
                    .or(contentLike(cond.getKeyword()))
                    .or(nameLike(cond.getKeyword())));
}

 

코드를 재사용하고자 하였기 때문에 기존 메서드를 합하여 만들었다. 이렇게 작성하였을 때 or 조건의 처음에 있는 코드가 null로 들어와 NullPointException이 발생하였다. 

 

기존에 있는 코드를 재활용하고 싶었기 때문에 조금 길지만 아래와 같이 적용하였다.

private BooleanExpression multiCondition(ProjectSearchCond cond) {
    BooleanExpression result = null;
    BooleanExpression skillMatch = projectSkillMatch(cond.getSkillCode());
    BooleanExpression positionSame = projectPositionSame(cond.getPositionCode());
    BooleanExpression contentLike = contentLike(cond.getKeyword());
    BooleanExpression nameLike = nameLike(cond.getKeyword());
    BooleanExpression statusSame = statusSame(cond.getStatus());
    if (skillMatch != null) {
        result = skillMatch.or(result);
    }
    if (positionSame != null) {
        result = positionSame.or(result);
    }
    if (contentLike != null) {
        result = contentLike.or(result);
    }
    if (nameLike != null) {
        result = nameLike.or(result);
    }
    if (statusSame != null) {
        result = statusSame.and(result);
    }
    return result;
}

 

 

'JPA' 카테고리의 다른 글

Querydsl 서브쿼리  (0) 2024.03.31
Querydsl 정리  (0) 2024.03.29
영속성 컨텍스트  (0) 2024.01.28
JPQL문법 2 (페치 조인,벌크 연산)  (0) 2022.12.23
JPQL 문법 1  (1) 2022.12.22