[Spring Boot] 페이징 ( + MyBatis, 타임리프)

[Spring Boot] 페이징 ( + MyBatis, 타임리프)

반응형

1. 페이징 처리를 위한 필드들 정의 (Pagination.class)

2. 총 컨텐츠 개수, 현재 페이지, 현재 페이지 블록(범위) 를 받아서 처리

3. 화면에 보여주기(View)

1. 프로젝트 구조

2. Pagination, Common 코드

@Data public class Pagination extends Common{ private int listSize = 10; // 초기값으로 목록개수를 10으로 셋팅 private int rangeSize = 10; // 초기값으로 페이지범위를 10으로 셋팅 private int page; // 현재 페이지 private int range; // 현재 페이지 범위 (1~10 = 1) private int listCnt; // 총 게시물 개수 private int pageCnt; // 총 페이지 개수 private int startPage; // 각 페이지 범위 중 시작 번호 private int startList; // mysql용 게시판 시작 번호 (0, 10, 20..) private int endPage; // 각 페이지 범위 중 마지막 번호 private boolean prev; // 이전 페이지 여부 private boolean next; // 다음 페이지 여부 public void pageInfo(int page, int range, int listCnt) { this.page = page; // 현재 페이지 this.listCnt = listCnt; // 게시물 개수 총합 // 페이지 범위 this.range = range; // 전체 페이지수 this.pageCnt = (int) Math.ceil((double) listCnt / listSize); // 시작 페이지 this.startPage = (range - 1) * rangeSize + 1 ; // 끝 페이지 this.endPage = range * rangeSize; // 게시판 시작번호 this.startList = (page - 1) * listSize; // 이전 버튼 상태 this.prev = range == 1 ? false : true; // 다음 버튼 상태 this.next = endPage > pageCnt ? false : true; if(this.endPage > this.pageCnt) { this.endPage = this.pageCnt; this.next = false; } } }

Pagination : 페이지 처리에 필요한 필드 Common을 상속받고 활용할 외부 정보를 저장

package com.min.board.paging; import lombok.Data; @Data public class Common { private String searchText; private String writer; private String type; }

Common : 메인 게시판, 내 글 관리, 휴지통 등 컨텐츠를 보여줄 때 아래 페이지 처리를 해야하는데 이 때 사용

searchText : 검색 기능이 필요한 페이지의 경우 사용

writer : 내 글 관리, 휴지통 등에서 사용자 정보를 저장

type : 메인 게시판, 내 글 관리, 휴지통 등 DB에서 가져오는 값이 다르므로 Mapper에서 문으로 동적 쿼리 진행

3. Mapper 코드

@Mapper public interface BoardMapper { // 게시글 개수 반환 (메인 게시글, 글 관리, 휴지통) int selectBoardTotalCount(Pagination pagination); // 게시글 리스트 (메인 게시글, 글 관리, 휴지통) List selectBoardList(Pagination pagination); }

id ,title ,content ,writer_id ,writer ,delete_yn ,create_date ,image SELECT FROM tb_board WHERE ORDER BY id DESC, create_date SELECT COUNT(*) FROM tb_board WHERE

LIMIT #{startList}, #{listSize} delete_yn = 'N' AND ( title LIKE CONCAT('%', #{searchText}, '%') OR content LIKE CONCAT('%', #{searchText}, '%') ) delete_yn = 'N' AND writer = #{writer} delete_yn = 'Y' AND writer = #{writer}

코드관리를 위해 CommonMapper로 동적 쿼리 진행할 코드를 분리

4. Service 코드

// 전체 게시글 개수 리턴 public int getBoardListCnt(Pagination pagination) { int boardTotalCount = 0; try { boardTotalCount = boardRepository.selectBoardTotalCount(pagination); } catch (Exception e) { System.out.println("boardRepository.getBoardListCnt() .. error : " + e.getMessage()); } finally { return boardTotalCount; } } // 전체 게시글 리스트로 리턴 public List getBoardList(Pagination pagination) { List boards = Collections.emptyList(); try { boards = boardRepository.selectBoardList(pagination); } catch (Exception e) { System.out.println("boardRepository.getMyBoardList() .. error : " + e.getMessage()); } finally { return boards; } }

5. Controller 코드

// 게시판 리스트 (게시글 페이징 및 검색 리스트) @GetMapping("/list") public String list(Model model, @RequestParam(required = false, defaultValue = "1") int page, @RequestParam(required = false, defaultValue = "1") int range, String searchText) { int listCount = 0; Pagination pagination = new Pagination(); pagination.setSearchText(searchText); pagination.setType("list"); listCount = boardService.getBoardListCnt(pagination); pagination.pageInfo(page, range, listCount); List boards = boardService.getBoardList(pagination); model.addAttribute("pagination", pagination); model.addAttribute("boardList", boards); return "board/list"; }

메인 게시판에 페이징 처리를 위해 page, range, searchText를 받아온다.

pagination에 검색어, type(게시판 = list, 내가쓴글 = myPost, 휴지통 = trash 등을 선언해 type에 맞는 동적 쿼리문 실행 유도)을 저장

listCount에 pagination 객체를 이용해서 총 게시글 개수를 저장

최종적으로 Pagination 객체에 page, range, listCount를 초기화

List 형태의 boards 를 생성해서 현재 페이지에 맞는 컨텐츠를 받아옴.

// 글 관리에서 삭제 @PostMapping("/myPost/delete") public String boardDelete(@RequestParam(required = false) List boardIdList) { if(boardIdList == null) return "redirect:/board/myPost"; if(boardIdList.size() > 0) { for(int i = 0; i < boardIdList.size(); i ++) { boardService.temporaryDelete(Long.parseLong(boardIdList.get(i))); } } return "redirect:/board/myPost"; }

6. View

총 건수 : Search . . . 1 제목 작성일 작성자

pagination.listCnt : 보여줄 게시글의 총 개수

input - hidden : name으로 컨트롤러로 page, range를 전송 (GET 방식이므로 url에 표시) value=${param.range}" : url에 표시되는 range= 3 값을 가져와 해당 input태그 값으로 셋팅

input - searchText : 컨트롤러로 searchText를 전송해서 결과값을 얻도록 유도 (th:value를 이용해서 검색후에도 해당 칸에 검색어가 그대로 남아있음)

: 테이블에 게시판 글을 보여주기위한 컨텐츠 th:each="board : ${boardList}"> : 컨트롤러에서 받아온 List형태인 boardList를 변수명 board로 정의해서 리스트 값을 꺼내서 사용 ${dates.format(board.createDate, 'yyyy/MM/dd HH:mm')} : 날짜 형식을 2021/12/28 19:48 로 변경 https://black-mint.tistory.com/31

th:replace="fragments/pagingCommon :: pagination(${pagination}, 'list')" : 프래그먼트를 이용해 분리된 페이징 화면을 불러와 사용 https://black-mint.tistory.com/19 의 3번.

list 화면

List No 제목 작성일 작성자 1 제목 작성일 작성자 Delete

myPost 화면

input - checbox : 내 글 관리에서 체크박스로 삭제할 컨텐츠를 체크하기 위한 체크박스 th:value를 이용해서 해당 체크박스의 값을 컨텐츠 id로 지정 name을 컨트롤러의 파라미터와 똑같은 이름으로 설정

Previous 1 Next

th:fragment : 위 코드들에서 th:replace 붙은 곳에 보여짐

th:block - th:with : 새로운 변수 초기화 후 사용

https://black-mint.tistory.com/19 의 4번에 정리

from http://black-mint.tistory.com/32 by ccl(A) rewrite - 2021-12-28 20:27:52