목록 처리와 평균 평점
- 등록 처리가 완료 되었더라면 목록 페이지를 제작합니다.
- 목록 페이지에는 영화의 제목과 이미지 평균 평점을 화면에 출력해야만 합니다.
- 예제에서 사용했던 PageRequestDTO 와 PageResultDTO를 dto패키지에 추가해줍니다.
MovieService와 MovieServiceImpl
- 영화와 평점 데이터는 이미 처리에 두었기 때문에 이를 이용하는 클래스를 수정해줍니다.
- MoviRepository 인터페이스의 getListPage() 메서드는 Movie 객체와 MovieImage 객체 하나,double 값으로 나오는 영화의 평균 평점/Long 타입의 리뷰 개수를 Object[]로 반환해줍니다.
MovieDTO 수정
- MovieServie의 getList()는 Movie,MovieImage,Double,Long을 Objecect[]배열을 리스트에 담은 형태 입니다.
- 각 Object[]를 MovieDTO 하나의 객체로 처리해야만 합니다.
- MovieDTO에는 Double 타입의 평점 평균과 리뷰의 개수를 처리하는 파라미터를 추가해줍니다.
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MovieDTO {
private Long mno;
private String title;
@Builder.Default
private List<MovieImageDTO> imageDTOList = new ArrayList<>();
private double avg;
private LocalDateTime regDate;
private LocalDateTime modDate;
}
MovieServie의 엔티티 변환
- MovieService에는 JPA를 통해서 나오는 엔티티 객체들과 Double,Long 등의 값을 MovieDTO로 변환하는 entityToDto()를 추가하고 컨트롤러가 호출할 때 사용할 getList()를 추가합니다.
- 추가된 entityToDto는 다음과 같은 파라미터를 받습니다.
-Movie 엔티티
-List엔티티(리스트로 받은 이유는 조회 화면에서 여러개의 이미지를 처리하기 위해서 입니다.)
-Double 타입의 평점 평균
-Long 타입의 리뷰 개수
public interface MovieService {
Long register(MovieDTO movieDTO);
PageResultDTO<MovieDTO,Object[]> getList(PageRequestDTO pageRequestDTO);
default MovieDTO entityToDto(Movie movie,List<MovieImage>movieImages,Double avg,Long reviewCnt){
MovieDTO movieDTO = MovieDTO.builder()
.mno(movie.getMno())
.title(movie.getTitle())
.regDate(movie.getRegDate())
.modDate(movie.getModDate())
.build();
List<MovieImageDTO>movieImageDTOList =movieImages.stream().map(movieImage -> {
MovieImageDTO movieImageDTO = MovieImageDTO.builder()
.imgName(movieImage.getImgName())
.path(movieImage.getPath())
.uuid(movieImage.getUuid())
.build();
return movieImageDTO;
}).collect(Collectors.toList());
movieDTO.setImageDTOList(movieImageDTOList);
movieDTO.setAvg(avg);
movieDTO.setReviewCnt(reviewCnt.intValue());
return movieDTO;
}
- MovieServiceImpl 클래스의 getList() 메서드를 구현해 줍니다.
@Override
public PageResultDTO<MovieDTO, Object[]> getList(PageRequestDTO pageRequestDTO) {
Pageable pageable = pageRequestDTO.getPageable(Sort.by("mno").descending());
Page<Object[]> result = movieRepository.getListPage(pageable);
Function<Object[],MovieDTO> fn = (arr ->entityToDto(
(Movie)arr[0],(List<MovieImage>) arr[1],(Double)arr[2],(Long) arr[3]));
return new PageResultDTO<>(result,fn);
}
@GetMapping("/list")
public void list(PageRequestDTO pageRequestDTO, Model model){
log.info("pageRequest : "+pageRequestDTO);
model.addAttribute("result",movieService.getList(pageRequestDTO));
}
- template의 movie 폴더에는 list.html 을 만들어 작성해줍니다.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<th:block th:replace="~{/layout/basic :: setContent(~{this::content} )}">
<th:block th:fragment="content">
<h1 class="mt-4">Movie List Page
<span><a th:href="@{/movie/register}"><button type="button" class="btn btn-outline-primary">Register</button></a></span>
</h1>
<form th:action="@{/movie/list}" th:method="get" id="searchForm">
<input type="hidden" name="page" value="1">
</form>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Title</th>
<th scope="col">Review Count</th>
<th scope="col">AVG Rating</th>
<th scope="col">RedDate</th>
</tr>
</thead>
<tbody>
<tr th:each="dto : ${result.dtoList}">
<th scope="row">
<a th:href="@{/movie/read(mno=${dto.mno},page=${result.page})}">
[[${dto.mno}]]
</a>
</th>
<td><img th:if="${dto.imageDTOList.size() > 0 && dto.imageDTOList[0].path != null }"
th:src="|/display?fileName=${dto.imageDTOList[0].getThumbnailURL()}|" ></td>
<td><b>[[${dto.reviewCnt}]]</b></td>
<td><b>[[${dto.avg}]]</b></td>
<td>[[${#temporals.format(dto.regDate, 'yyyy/MM/dd')}]]</td>
</tr>
</tbody>
</table>
<script th:inline="javascript">
</script>
</th:block>
</th:block>
</html>
- 영화 이미지는 imageDTOList의 크기가 0보다 크고 path 속성에 값이 있는 실제 이미지가 존재할 때만
<img>
태그를 생성합니다.
- 화며에 페이지를 출력하는 부분은 이전 예제들과 동일합니다.
<table>
태그가 끝난 부분에 아래의 코드를 추가해 줍니다.
<ul class="pagination h-100 justify-content-center align-items-center">
<li class="page-item " th:if="${result.prev}">
<a class="page-link" th:href="@{/movie/list(page= ${result.start -1})}" tabindex="-1">Previous</a>
</li>
<li th:class=" 'page-item ' + ${result.page == page?'active':''} " th:each="page: ${result.pageList}">
<a class="page-link" th:href="@{/movie/list(page = ${page})}">
[[${page}]]
</a>
</li>
<li class="page-item" th:if="${result.next}">
<a class="page-link" th:href="@{/movie/list(page= ${result.end + 1} )}">Next</a>
</li>
</ul>
- 화면에서는 페이지 번호가 출력되는 것을 볼 수 있고 실제 페이지의 이동도 가능합니다.