영화/리뷰 프로젝트 적용하기-(3)
목록 처리와 평균 평점
- 등록 처리가 완료 되었더라면 목록 페이지를 제작합니다.
- 목록 페이지에는 영화의 제목과 이미지 평균 평점을 화면에 출력해야만 합니다.
- 예제에서 사용했던 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; //리뷰 수 jpa의 count()
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);
//생략
//Entity -> DTO 변환
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);
}
- 목록화면과 MovieController 처리
@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>
- 화면에서는 페이지 번호가 출력되는 것을 볼 수 있고 실제 페이지의 이동도 가능합니다.
Author And Source
이 문제에 관하여(영화/리뷰 프로젝트 적용하기-(3)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@jyyoun1022/영화리뷰-프로젝트-적용하기-3
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
@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; //리뷰 수 jpa의 count()
private LocalDateTime modDate;
}
-Movie 엔티티
-List엔티티(리스트로 받은 이유는 조회 화면에서 여러개의 이미지를 처리하기 위해서 입니다.)
-Double 타입의 평점 평균
-Long 타입의 리뷰 개수
public interface MovieService {
//등록처리
Long register(MovieDTO movieDTO);
//목록처리
PageResultDTO<MovieDTO,Object[]> getList(PageRequestDTO pageRequestDTO);
//생략
//Entity -> DTO 변환
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;
}
@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));
}
<!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>
<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>
Author And Source
이 문제에 관하여(영화/리뷰 프로젝트 적용하기-(3)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jyyoun1022/영화리뷰-프로젝트-적용하기-3저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)