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을 지정해주면 끝.