스프링수업 18일차
한 일
- 페이징
- 페이지네이션
페이징
추후 개념보충 필요
오라클의 ROWNUM을 이용한 방법
1. 모든 데이터의 행에 순서를 매긴 후 필요한 순번을 가져오기
2. 필요한 데이터의 순번까지만 순서를 매긴 후 바로 가져오기
MySQL의 LIMIT을 이용한 방법
LIMIT <skip> <count>
# 처음부터 3개 건너뛴 후 4개 출력 SELECT * FROM board LIMIT 3, 4;
페이징 객체 생성
페이지를 처리할 변수를 저장하기 위한 클래스 생성
- Criteria -
public class Criteria {
private int pageNum; // 현재 페이지
private int amount; // 한 페이지당 보여질 게시물 수
private int skip; // 스킵할 게시물 수 ((pageNum - 1 ) * amount)
// 기본생성자 => 기본세팅: pageNum = 1, amount = 10
public Criteria() {
this(1, 10); // 전체 생성자를 통해 (1, 10)을 입력해 객체 생성
}
// 생성자 => 원하는 pageNum, 원하는 amount
public Criteria(int pageNum, int amount) {
this.pageNum = pageNum;
this.amount = amount;
this.skip = (pageNum - 1 ) * amount;
}
public int getPageNum() {
return pageNum;
}
// 새로 페이지 수를 설정했을 때 skip도 계산
public void setPageNum(int pageNum) {
this.pageNum = pageNum;
this.skip = (pageNum - 1 ) * amount;
}
public int getAmount() {
return amount;
}
// 페이지당 데이터 갯수를 바꿀 경우에도 skip을 다시 계산
public void setAmount(int amount) {
this.amount = amount;
this.skip = (pageNum - 1 ) * amount;
}
public int getSkip() {
return skip;
}
public void setSkip(int skip) {
this.skip = skip;
}
@Override
public String toString() {
return "Criteria [pageNum=" + pageNum + ", amount=" + amount + ", skip=" + skip + "]";
}
}
skip(뛰어넘을 게시글 수)은 계산을 통해 만들어짐. 입력받는 필드는 pageNum과 amount만.
skip은 계산으로 산출되는 필드이므로 pageNum이나 amount의 숫자가 변경될 경우 다시 계산하도록 set메서드 생성 시 계산식을 작성해준다.
페이징 쿼리문 작성
- BoardMapper -
// 게시판 목록(페이징 적용). pageNum과 amount를 입력받아 객체 cri생성. 없으면 기본값(1, 10)적용
public List<BoardVO> getListPaging(Criteria cri);
페이징을 적용한 게시판목록을 불러오는 List를 추가.
- BoardMapper.xml -
<!-- 게시판 목록 (페이징) : skip과 amount는 Criteria 객체에서 입력됨 -->
<select id="getListPaging" resultType="BoardVO">
SELECT * FROM (
SELECT bno, title, writer, regdate, updatedate
FROM board ORDER BY bno DESC) as T1
LIMIT #{skip}, #{amount}
</select>
bno가 큰순 = 최신 게시글이 위로 가장 올라오는 순서로 불러옴
TRUNCATE TABLE board; # 모든 행 삭제
# 프로시저 시작
DELIMITER $$
DROP PROCEDURE IF EXISTS procedureName$$
CREATE PROCEDURE procedureName()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i <= 100 DO
INSERT INTO board(title , content, writer, regDate, updateDate)
VALUES( concat('제목',i), '테스트 데이터 에요', '작가' , now(), now());
SET i = i + 1;
END WHILE;
END$$
DELIMITER $$
CALL procedureName; # 프로시저 호출
프로시저 내부에 한글주석이 있으면 실행이 안되니 주의.
프로시저를 실행하면 데이터 100개가 insert됨.
테스트
- BoardMapperTests -
// 페이징 테스트
@Test
public void testGetListPaging() {
Criteria cri = new Criteria();
List<BoardVO> list = boardMapper.getListPaging(cri);
list.forEach(board -> log.info("" + board));
}
기본값대로 1페이지, 한 페이지당 10개의 게시글을 보여줌
pageNum과 amount를 2, 5로 바꿔서 테스트해보기.
@Test
public void testGetListPaging() {
Criteria cri = new Criteria();
cri.setPageNum(2);
cri.setAmount(5);
List<BoardVO> list = boardMapper.getListPaging(cri);
list.forEach(board -> log.info("" + board));
}
service에 페이징 적용
- BoardService -
public List<BoardVO> getListPaging(Criteria cri); // 페이징 적용 게시글목록
- BoardServiceImpl -
@Override
public List<BoardVO> getListPaging(Criteria cri) {
return boardMapper.getListPaging(cri);
}
- BoardController -
@GetMapping("/list")
public String boardListGet(Criteria cri, Model model) {
// boardList에 모든 게시글을 전달
model.addAttribute("boardList", boardService.getListPaging(cri));
return "list";
}
원래있던 boardListGet메서드는 주석처리 후 페이징 된 게시글리스트를 전달하도록 새 메서드 생성.
cri에 값을 지정해주지 않으면 기본값인 (1, 10)이 적용되고, 값을 따로 정해주면 그 값대로 현재페이지와 한 페이지당 게시글 갯수가 변경됨.
http://localhost:8080/board/list
/list로 접근 시 기본페이징인 가장 첫 페이지만 출력됨
http://localhost:8080/board/list?pageNum=5&amount=15
parameter로 pageNum, amount에 값을 넘겨 현재페이지와 한페이지당 게시글수를 변경할 수 있음
페이지네이션
페이지 계산을 위한 클래스생성
- PageMakerDTO -
private int startPage; // 시작 페이지
private int endPage; // 끝 페이지
private boolean prev, next; // 이전, 다음페이지 존재유무
private int total; // 전체 게시글 수
private Criteria cri; // 현재 페이지, 페이지당 게시글 표시 수 정보
public PageMakerDTO(int total, Criteria cri) {
this.total = total;
this.cri = cri;
// 마지막페이지(현재 페이지네이션바의 마지막 숫자): 10 단위로 표시 1~10, 11~20, 21~30
// Math.ceil은 소수점을 정수로 올림
this.endPage = (int)(Math.ceil(cri.getPageNum() / 10.0)) * 10;
// 시작 페이지
this.startPage = this.endPage - 9;
// 실제 마지막 페이지 (총 마지막 페이지)
int realEnd = (int)(Math.ceil(total * 1.0 / cri.getAmount()));
// 전체 마지막 페이지(realEnd)가 화면에 보이는 마지막페이지(endPage)보다 작은 경우, 보이는 페이지(endPage) 값 조절
if(realEnd < this.endPage) {
this.endPage = realEnd;
}
// < 이전페이지 참? 시작 페이지(startPage)값이 1보다 큰 경우 true
this.prev = this.startPage > 1;
// > 다음페이지 참? 마지막 페이지(endPage)값이 1보다 큰 경우 true
this.next = this.endPage < realEnd;
}
// get/set toString 메서드 자동생성
ceil
은 올림함수
pageNum
이 1이면 0.1 => 올림으로 0.1~1.0까지는 모두 1이 됨. 즉 pageNum이 1~10까지는 1이 됨.
=> 현재 페이지가 1 ~ 9라면 끝 페이지는 모두 10이 된다는 뜻. 페이지네이션바에 1부터 10까지의 페이지숫자가 나오게 됨.
- BoardMapper -
public int getTotal(); // 게시글 총 갯수
총 게시글 수를 계산하는 메서드 추가
- BoardMapper -
<!-- 게시글 총 갯수 -->
<select id="getTotal" resultType="int">
SELECT count(*) FROM board;
</select>
테스트
- BoardMapperTests -
// 총 게시글 수
@Test
public void testGetTotal() {
int result = boardMapper.getTotal();
log.info("총 개시글 수: " + result);
}
service에 페이지네이션 적용
- BoardService -
public int getTotal(); // 게시글 총 갯수
- BoardServiceImpl -
@Override
public int getTotal() {
return boardMapper.getTotal();
}
- BoardController -
boardListGet 수정
// 게시글 목록 페이지 (페이징 적용)
@GetMapping("/list")
public String boardListGet(Criteria cri, Model model) {
// boardList에 페이징 된 모든 게시글을 전달
model.addAttribute("boardList", boardService.getListPaging(cri));
int total = boardService.getTotal();
PageMakerDTO pmk = new PageMakerDTO(total, cri); // 객체 생성 시 모든 변수 계산됨
model.addAttribute("pmk", pmk); // 페이지네이션을 위한 pmk객체 전달
return "list";
}
- list.html -
<nav aria-label="Page navigation" th:if="${pmk.endPage > 0}">
<ul class="pagination">
<li class="page-item">
<a class="page-link" href="javascript:;" aria-label="이전">
<span class="material-icons"> keyboard_arrow_left </span>
<span class="sr-only">이전</span>
</a>
</li>
<li class="page-item" th:each="number : ${#numbers.sequence(1, pmk.endPage)}"><a class="page-link" href="javascript:;" th:text="${number}"></a></li>
<li class="page-item">
<a class="page-link" href="javascript:;" aria-label="다음">
<span class="material-icons"> keyboard_arrow_right </span>
<span class="sr-only">다음</span>
</a>
</li>
</ul>
</nav>
Author And Source
이 문제에 관하여(스프링수업 18일차), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@0829kuj/스프링수업-18일차저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)