테마 리스트에서 리뷰 평점을 출력하는데

SQL문이 그냥 ~ avg(reviews.rating) ~ 으로 나가기 때문에
저렇게 표시되는 것을 볼 수 있었다.
소수점 둘째짜리까지 나오도록 반올림해서 출력해보자 !
현재 상태는 select 절 안에 아래와 같이 입력되어 있다.
review.rating.avg().coalesce(-1.0)
시도 1. round() 함수 - 실패
review.rating.avg().coalesce(-1.0).round()

이와 같이 소수점 첫째자리에서 반올림된다.
round(2) 와 같이 파라미터를 넣어보려고 했지만 불가능했다.
SQL문도 round(coalesce(avg(reviews2_.rating), -1.0)) 으로 출력되는 것을 확인 ..
시도 2. Expressions.template() 메서드 사용 (데이터베이스 방언에 따라 패턴 설정) - 성공
Expressions.template(Double.class, "ROUND({0}, 2)", review.rating.avg().coalesce(-1.0))

성공 .. !
Expressions.template() 메서드를 사용하여 MySQL의 ROUND() 함수를 쿼리에 적용하였다. (본인이 설정해놓은 데이터베이스 방언에 따라 조금 다를 수 있음)
쿼리에 ROUND 함수를 적용하였고, {0} 자리에 review.rating.avg().coalesce(-1.0)을 삽입한다는 뜻이다.
나는 ROUND({0}, 2) 라고 했기 때문에 소수점 둘째 자리까지 반올림되어 표시되었다.
만약 n번째 자리에서 반올림하고 싶다면 ROUND({0}, 2) 에서 2 부분을 원하는대로 바꾸면 된다. (MySQL의 ROUND 함수 사용법 참고)
p6spy 로그를 보니 select 절에 내가 의도한 대로 아래와 같이 쿼리가 나간 것을 확인할 수 있었다 ! ㅎㅎ
round(coalesce(avg(reviews2_.rating), -1.0), 2)
혹시 위의 코드가 길어서 불편하다면
NumberExpression<Double> avgRating = review.rating.avg().coalesce(-1.0));
NumberExpression<Double> roundedAvgRating = Expressions.template(Double.class, "ROUND({0}, 2)", avgRating);
이런 식으로 메서드를 추출해도 된다..
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.core.types.dsl.NumberExpression;
NumberExpression<Double> avgRating = review.rating.avg();
NumberExpression<Double> roundedAvgRating = Expressions.template(Double.class, "ROUND({0}, 2)", avgRating);
queryFactory
.select(new QThemeListDTO(
theme.id,
theme.name,
roundedAvgRating))
.from(theme)
.leftJoin(theme.cafe, cafe)
.leftJoin(theme, review.theme)
.orderBy(roundedAvgRating.desc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
전체 코드
https://github.com/maemae22/escape-room/commit/5648c699f5334bc323334f0f9199b3976d1a32c2
refactor: #21 - 리뷰 평점 반올림하여 소수점 둘째 자리로 출력되도록 변경 · maemae22/escape-room@5648c69
- Expressions.template() 메서드를 사용하여 ROUND(@@, 2) 함수를 적용함 - 정리 : https://maemae22.tistory.com/114
github.com