Spring/JPA + Security
[Spring Data JPA] 좋아요 구현하기 -5 좋아요 높은 순서의 인기 페이지 구현하기
pyogowoon
2023. 1. 13. 17:25
좋아요 (Likes) 가 있는 게시글들은 따로 popular 페이지에서 뜨게 할 수 있는 로직을 만듭니다.
@GetMapping("/image/popular")
public String popular(Model model) {
//api는 데이터를 리턴하는 서버 여서 이건 그냥 ajax없이 들고가기만 해서
//컨트롤러에 구현
List<Image> images = imageService.인기사진();
model.addAttribute("images", images);
return "image/popular";
}
세션을 들고가야 하기 떄문에 model을 매개변수로 넣어주었고
따로 ajax를 사용하지 않고 단순 데이터를 옮기기만 할 것이기 떄문에 imageController 에 구현합니다.
@Transactional(readOnly = true)
public List<Image> 인기사진(){
return imageRepository.mPopular();
}
리포지토리에 네이티브 쿼리를 구현할 것이기 떄문에 쿼리를 먼저 생성합니다.
우리는 결국 내용 , postImageUrl , userId 가 나와야 하고
좋아요가 높은 순서의 DB쿼리가 필요한 셈이다.
SELECT imageId, COUNT(imageId) likeCount FROM likes GROUP BY imageId;
imageId | likeCount |
2 | 1 |
3 | 2 |
의 쿼리에서 우리가 원하는 쿼리는 likeCount가 높은 순서대로 나오는것이다, 이걸 1행을 지키면서 조인할 수 있는 쿼리가 밑에 쿼리이다.
SELECT i.* FROM image i INNER JOIN (SELECT imageId, COUNT(imageId) likeCount FROM likes GROUP BY imageId) c ON i.id = c.imageId ORDER BY likeCount DESC;
하면 해당 쿼리가 완성됩니다. 여기서 SELECT 에 i.* 을 붙여준 이유는 이 과정에서 c 쿼리이 imageId 와 likeCount는 단순 계산을 위한 컬럼이고 Image 도메인에 없는 가상의 컬럼이기 때문에 SELECT 에서 제외 시켜준다.
@Query(value=" SELECT i.* FROM image i INNER JOIN (SELECT imageId, COUNT(imageId) likeCount FROM likes GROUP BY imageId) c ON i.id = c.imageId ORDER BY likeCount DESC", nativeQuery = true)
List<Image> mPopular();
ImageRepository 에 해당 쿼리를 넣어주고
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="../layout/header.jsp"%>
<!--인기 게시글-->
<main class="popular">
<div class="exploreContainer">
<!--인기게시글 갤러리(GRID배치)-->
<div class="popular-gallery">
<c:forEach var="image" items="${images}">
<div class="p-img-box">
<a href="/user/${image.user.id}"> <img src="/upload/${image.postImageUrl}" />
</a>
</div>
</c:forEach>
</div>
</div>
</main>
<%@ include file="../layout/footer.jsp"%>
데이터를 가져간 popular.jsp 에서 ForEach을 돌려주고, 가져온 DB안에서 id와 url을 지정해주면 끝.