동적 쿼리에 대한 기능을 수정이 필요하여 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 |