담당 기능
글쓴이는 담당 기능을 끝내고 팀원 분들의 기능을 하나씩 맡아서 기능 구현을 해주는 팀장을 담당하고 있습니다!
오늘은 리뷰 게시판을 담당하는 팀원분들의 기능인 별점 기능을 구현하고 평균값을 계산해서 view 단에 표출하는 작업을 해보겠습니다.
구현 방식은 ratingDTO를 생성해서 리뷰 게시글 평점의 편균 값이 저장되도록 하는 것이 목표입니다.
구현을 위해서 mapper 파일에 쿼리문을 먼저 작성하고, DAO -> Service -> Controller ->View 순서대로 진행해 보겠습니다.
프로젝트 구조는 다음과 같습니다.
프로젝트 구조
mapper
mapper 파일에서는 평점 평균값을 최신화해주는 select문과 평점을 반영할 수 있는 insert문을 작성하고, 미리 id값을 정해서 쿼리문을 작성했습니다.
<mapper namespace="rating">
<select id="ratingAvg" resultType="double">
select avg(rating)
from rating g, review w
where g.review_num =w.review_num and g.review_num=#{review_num}
</select>
<insert id="ratingInsert">
insert into rating
(review_num,rating) values (#{review_num},#{rating})
</insert>
</mapper>
DTO
데이터 맵핑을 위한 DTO를 생성해 줍니다.
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class RatingDTO {
private Long t_num; // 시퀀스
private Integer mem_num; // 회원 번호
private Integer review_num; // 리뷰 번호
private Double rating; // 별점
private Double ratingAvg; // 별점 총합
}
DAO
DTO를 생성하고 쿼리문 작성을 했다면, 연결해 주는 DAO를 생성해서 mapper와 연결해 주는데,
쿼리문을 select, insert 두 개를 생성했기 때문에 메서드를 두 개 생성해서 연결해 줍니다.
@Override
public Double ratingAvg(Integer review_num) {
return sqlSession.selectOne("rating.ratingAvg",review_num);
}
@Override
public void ratingInsert(RatingDTO dto) {
sqlSession.insert("rating.ratingInsert",dto);
}
Service
Serivce단에서는 비즈니스 로직을 작성하는 부분인데, 평점 평균값이 제대로 최신화가 되는지 확인하기 위해 순수 DAO 연결 코드만 작성해서 구현했습니다.
(디테일 작업은 추후에 올리겠습니다.)
@Override
public Double ratingAvg(Integer review_num) {
return reviewDao.ratingAvg(review_num);
}
@Override
public void ratingInsert(RatingDTO dto) {
reviewDao.ratingInsert(dto);
}
Controller
Service 단 까지 코드 작업이 끝났다면
View단에 데이터 맵핑을 시켜주기 위해 Controller단에 평점 코드를 구현해줘야 합니다.
그렇다면 먼저 코드를 추가해야 할 곳은 별점 기능이 구현되어 있는 리뷰 상세 페이지 코드에 평점 평균값 코드를 추가해줘야 합니다.
@GetMapping("/review/detail")
public ModelAndView detail(Integer review_num,
HttpServletRequest request,
HttpServletResponse response) {
reviewService.count(review_num, request,response);
ReviewDTO review = reviewService.detail(review_num);
/*평점 total 값 추가 */
Double ratingavg = reviewService.ratingAvg(review_num);
ModelAndView mav = new ModelAndView();
mav.setViewName("review/detail");
mav.addObject("review", review);
/* 뷰단에 보내주기 */
mav.addObject("ratingAvg", ratingavg);
return mav;
}
View단에 데이터 맵핑을 시켜주기 위해 addObject ()를 활용했습니다.
다음으로는 평점 등록 버튼 클릭 시 반영되는 insert 경로 및 코드 연결을 해줘야 합니다.
@RequestMapping("/review/ratinginsert")
public String ratingInsert( Integer review_num, Double rating , Model model){
RatingDTO dto = new RatingDTO();
dto.setReview_num(review_num);
dto.setRating(rating);
reviewService.ratingInsert(dto);
Double ratingavg = reviewService.ratingAvg(review_num);
model.addAttribute("dto", ratingavg);
return "/review/rating";
}
VIew
평균 평점 값은 ajax를 활용해서 최신화할 수 있게 구현했습니다.
<div class="text-center border-bottom mt-3">
<h6>별점을 등록하세요</h6>
<div class="d-flex justify-content-center align-items-center">
<fieldset class="rate">
<input type="radio" id="rating10" name="rating" value="10.0" class="rating"><label for="rating10" title="5점"></label>
<input type="radio" id="rating9" name="rating" value="9.0" class="rating"><label class="half" for="rating9" title="4.5점"></label>
<input type="radio" id="rating8" name="rating" value="8.0" class="rating"><label for="rating8" title="4점"></label>
<input type="radio" id="rating7" name="rating" value="7.0" class="rating"><label class="half" for="rating7" title="3.5점"></label>
<input type="radio" id="rating6" name="rating" value="6.0" class="rating"><label for="rating6" title="3점"></label>
<input type="radio" id="rating5" name="rating" value="5.0" class="rating"><label class="half" for="rating5" title="2.5점"></label>
<input type="radio" id="rating4" name="rating" value="4.0" class="rating"><label for="rating4" title="2점"></label>
<input type="radio" id="rating3" name="rating" value="3.0" class="rating"><label class="half" for="rating3" title="1.5점"></label>
<input type="radio" id="rating2" name="rating" value="2.0" class="rating"><label for="rating2" title="1점"></label>
<input type="radio" id="rating1" name="rating" value="1.0" class="rating"><label class="half" for="rating1" title="0.5점"></label>
</fieldset>
<%-- <c:if test="${mem_num != null}">--%>
<button class="btn rating btn-outline-success" type="button" id="rating_btn">등록</button>
<%-- </c:if>--%>
<h3 class="mt-2 ps-2 pe-2 text-muted">/</h3>
<i class="bi bi-star-fill me-1"></i>
<div id="result"><%--total--%>
<h3 class="mt-2">
<fmt:formatNumber value="${ratingAvg}" pattern="0.0"/>
</h3> <%-- total--%>
</div>
</div>
</div>
<script>
$("#rating_btn").on("click", function () {
const review_num = ${review.review_num};
const rating = $(".rating:checked").val();
console.log("rate = " + rating);
console.log("review_num = " + review_num);
const data = {
review_num: review_num,
rating: rating
};
$.ajax({
data: data,
type: 'POST',
url: "${path}/review/ratinginsert",
success: function(result){
if(confirm("별점 등록 완료")){
$("#result").html(result);
}
}
});
});
추가적으로 최신화 할 수 있는 페이지, success 요청을 보냈던 result에 띄워줄 페이지를 생성해줘야 합니다.
즉, 등록 버튼을 클릭하면 ajax가 요청을 받아서 ratinginsert 경로인 Controller에 요청을 보냅니다.
그렇다면 Controller에서 ratinginsert url 맵핑을 했던 코드인 ratingInsert 메서드가 호출이 되는데,
결과를 확인하려면 리턴 시켜주는 페이지인 rating view 파일을 생성해줘야 합니다
rating 페이지는 간단하게 평균 총점만 변경되는 코드로 작성했습니다.
< rating >
<h3 class="mt-2"><fmt:formatNumber value="${dto}" pattern="0.0"/></h3>
<script>
console.log("dto =" + ${dto});
</script>
구현 결과
< 리뷰 게시판 >
< 리뷰 상세 페이지 >
< result >
마치며
오늘은 별점 기능 구현에 대해서 포스팅을 해보았습니다.
다음 포스팅에서 뵙겠습니다.
'[ Project ] > Team' 카테고리의 다른 글
[ Team ] OAuth - Naver API DB 연동 (0) | 2023.06.27 |
---|---|
[ Team ] 리뷰게시판 - 조회수 기능 구현 (0) | 2023.06.26 |
[ Team ] 인터셉터(Interceptor) 구현 (0) | 2023.06.21 |
[ Team ] 회원관리 - 페이지네이션 처리 기능 구현 (0) | 2023.06.20 |
[ Team ] OAuth - Kakao API 로그인 구현 (0) | 2023.06.17 |