해당 포스팅은 로그인 후 사용자의 마이 페이지에서 회원의 총 주문 금액과 포인트를 표시하기 위해 JPQL을 사용하여 해당 정보를 조회하는 과정에서 발생한 문제와 해결 방법을 다루고자 한다.
총 2가지의 문제가 발생했다.
아래는 문제가 발생한 쿼리이다.
/* OrderRepository.java */
@Query(value = "select new com.windsome.dto.MyPageDto(sum(o.totalOrderPrice), a.point) from Order o join Account a on o.account.id = a.id where o.account.id = :accountId and a.id = :accountId")
MyPageDto getMyPageInfo(@Param("accountId") Long accountId);
/* MyPageDto.java */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyPageDto {
private int totalOrderPrice;
private int totalPoint;
}
문제의 원인은 MyPageDto의 totalOrderPrice의 타입이 Long 타입이 아닌 int 타입으로 설정되어 있기 때문이었다. sum() 함수를 사용할 때는 int 타입이 아닌 Long 타입으로 반환된다는 사실을 간과했다. 따라서 MyPageDto의 totalOrderPrice의 타입을 Long 타입으로 변경하여 문제를 해결했다.
문제의 원인은 sum() 함수의 동작 방식에 있었다. JPA에서 sum() 함수는 모든 컬럼 값이 null인 경우 null을 반환한다. 따라서 sum() 함수의 리턴 값이 null인 경우 0을 반환하도록 COALESCE 함수를 사용하여 문제를 해결했다.
COALESCE 함수는 값이 null일 경우 두 번째 파라미터 값을 리턴하는 함수이다.
/* OrderRepository.java */
@Query(value = "select new com.windsome.dto.MyPageDto(coalesce(sum(o.totalOrderPrice), 0), a.point) from Order o join Account a on o.account.id = a.id where o.account.id = :accountId and a.id = :accountId")
MyPageDto getMyPageInfo(@Param("accountId") Long accountId);
/* MyPageDto.java */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MyPageDto {
private int totalOrderPrice;
private int totalPoint;
}