각 레이어간의 역할을 확실히 분리하기 위해서 클라이언트에 전달 할 객체는 항시 DTO로 변환해서 전달 합니다.
이떄 Spring Data Jpa 에서 제공하는 Pageable을 사용할 경우 반환받은 Page<Entity>를 Page<DTO>로 변환하는 상황이 생겨서 기록하였습니다.
1. Repository
public interface BoardRepository extends JpaRepository<Board, Long> {
// Containing : like와 비슷한 문법
Page<Board> findByTitleContainingOrContentContaining(String title, String content, Pageable pageable);
}
'title'과 'content'를 인자값으로 전달받아 where 검색결과를 return하도록 설정하였습니다.
2. Controller
/* 게시글 목록 */
@GetMapping
public String list(Model model, @PageableDefault(size = 10) Pageable pageable, @RequestParam(defaultValue = "") String searchTerm){
Page<Board> boardList = boardRepository.findByTitleContainingOrContentContaining(searchTerm, searchTerm, pageable);
Page<BoardDto> boardDtoList = new BoardDto().toDtoList(boardList); // Page<Entity> -> Page<Dto> 변환.
int startPage = Math.max(1, boardDtoList.getPageable().getPageNumber() - 10);
int endPage = Math.min(boardDtoList.getTotalPages(), boardDtoList.getPageable().getPageNumber() + 10);
model.addAttribute("startPage", startPage);
model.addAttribute("endPage", endPage);
model.addAttribute("boardDtoList", boardDtoList);
return "board/list";
}
boardRepository에서 전달받은 Page<Board> boardList를 BoardDto 클래스의 toDtoList 메소드에 인자로 담아서 호출합니다.
3. DTO (객체지향에 가깝게 대부분의 비즈니스 로직들은 해당 Entity나 DTO에서 호출하여 처리합니다)
/* Page<Entity> -> Page<Dto> 변환처리 */
public Page<BoardDto> toDtoList(Page<Board> boardList){
Page<BoardDto> boardDtoList = boardList.map(m -> BoardDto.builder()
.id(m.getId())
.type(m.getType())
.title(m.getTitle())
.content(m.getContent())
.writer(m.getUser().getUid())
.regdate(m.getRegdate())
.views(m.getViews())
.build());
return boardDtoList;
}
전달받은 boardList를 람다식 .map을 이용하여 Build한 후 Page<BoardDto>로 반환 받습니다.
4. HTML (타임리프)
<!-- 페이징 처리 -->
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-center">
<li class="page-item" th:classappend="${1 == boardDtoList.pageable.pageNumber + 1} ? 'disabled'">
<a class="page-link" th:href="@{/board(page=${boardDtoList.pageable.pageNumber}-1, searchTerm=${param.searchTerm})}" tabindex="-1" aria-disabled="true">이전</a>
</li>
<li class="page-item" th:classappend="${page == boardDtoList.pageable.pageNumber + 1} ? 'disabled'" th:each="page : ${#numbers.sequence(startPage, endPage)}">
<a class="page-link" th:href="@{/board(page=${page} - 1, searchTerm=${param.searchTerm})}" th:text="${page}">1</a>
</li>
<li class="page-item" th:classappend="${boardDtoList.totalPages == boardDtoList.pageable.pageNumber + 1} ? 'disabled'">
<a class="page-link" th:href="@{/board(page=${boardDtoList.pageable.pageNumber} + 1, searchTerm=${param.searchTerm})}">다음</a>
</li>
</ul>
</nav>
<!-- // 페이징 처리 -->
전달 받은 pageable 메소드들이 정상적으로 호출되는 것을 확인합니다
'JPA' 카테고리의 다른 글
[JPA] 더티 체킹(Dirty Checking)? + 동시성 이슈/제어 (2) | 2024.06.13 |
---|---|
[JPA] 엔티티 설계시 주의점 (0) | 2021.11.26 |
[JPA] 변경 감지(Dirty Checking) 와 병합(merge) (0) | 2021.09.16 |
[JPA] Spring Data JPA를 이용한 페이징 처리 (0) | 2021.08.19 |