๋ชฉ์ฐจ
ํ์ด์ง๋ค์ด์ ์ฒ๋ฆฌ ๊ด๋ จํด์ ๋ฏธ๋์ ๋ด๊ฐ ๋ณด๊ธฐ ์ํด ๊ธฐ๋ก ๐
์น๊ฐ๋ฐ์ ๊ธฐ์ด ์ค ๊ธฐ์ด๋ผ๊ณ ํ ์ ์๋ ํ์ด์ง๋ค์ด์ (ํ์ด์ง) ์ฒ๋ฆฌ์ ๋ํด์ ๊ฐ๋ตํ๊ฒ ์ ๋ฆฌ
๊ทธ๋์์ ์๋ฆฌ๋ฅผ ์ ๋๋ก ์ดํดํ์ง ๋ชปํ๊ณ ์ผ๋ค๋ฉด ์ด์ ํต์ฌ์์ฃผ๋ก ์ ์ ๋ฆฌํด ๋ณด์.
์๊ฐ ์ ํ์ด์ง ์ฒ๋ฆฌ๋ ๋์์ธ์ ์์ฒ๋ผ ํ๋๋ ์ ์ด์์ง๋ง ๋ฐ์ดํฐ๊ฐ ์ ๋์ค๋์ง ์์ฃผ๋ก ์์ฑํจ
๊ฐ๋ฐํ๊ฒฝ
back-end: springBoot 2.6.13(jdk 1.8)/mybatis 3.5.9/h2 database H2 2.1.214 (2022-06-13)(mode๋ mySQL๋ก ์ค์ )
front-end: thymeleaf/javascript/jQuery
์์๋ฅผ ์ํ ํ ์ด๋ธ
CREATE TABLE t_board(
board_id bigint auto_increment,
title varchar (30),
content varchar (30),
name varchar (30),
reg_date timestamp,
update_date timestamp,
primary key(board_id)
);
ํ ์คํธ ๋ฐ์ดํฐ ๋ฃ๋ ๊ฒ์ ์๋ต
DBMS๋ mysql ๊ธฐ์ค์ผ๋ก ์์ฑ
์ฟผ๋ฆฌ์์ ๋ฐ์ดํฐ๋ฅผ ์ ํ ๊ฑธ์ด์ ๊ฐ์ ธ์์ผ ํจ
limit์ ์ค๋ช ์ ์๋ตํจ(์์๊ฐ, ๊ฐ์ ธ์ฌ ๋ฐ์ดํฐ ๊ฑด์)

์ฟผ๋ฆฌ๋ limit๋ง ๊ฑธ์ด์ ๊ฐ์ ธ์ค๋ฉด ๋๋ค.
๋ค๋ง limit์ ๋ค์ parameter๊ฐ ํ๋ฉด์์ ์ฌ์ฉ์๊ฐ ํด๋ฆญํด์ ๋์ด์จ ๊ฐ๋ค๋ก ๋ณ์ ์ฒ๋ฆฌ๋์ด์ผ ํ๋ค๋ ๊ฒ
1ํ์ด์ง๋ limit 0, 10
2ํ์ด์ง๋ limit 10,10
3ํ์ด์ง๋ limit 20,10 ์ด๋ ๊ฒ ์ฒ๋ฆฌ๊ฐ ๋์ด์ผ ํ๋ค.
mapper xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- column๊ณผ vo์ field๋ช
์ด ์์ดํด์ resultMap ์ ์ธ -->
<mapper namespace="paging.study.mapper.BoardMapper">
<resultMap id="boardMap" type="paging.study.domain.vo.BoardVO">
<id column="board_id" property="boardId"/>
<result column="title" property="title"/>
<result column="content" property="content"/>
<result column="name" property="name"/>
<result column="reg_date" property="regDate"/>
<result column="update_date" property="updateDate"/>
</resultMap>
<!-- ํ์ฌ ํ์ด์ง ๋ฒํธ์ ๊ฐ์ ธ์ฌ ๋ฐ์ดํฐ ๊ฐ์๊ฐ ์๋ Criteria๋ฅผ parameter๋ก ๋ฐ์ limit์ ์ ํ์ฉ -->
<select id="findBoardListPaging" parameterType="paging.study.domain.Criteria" resultMap="boardMap">
SELECT * FROM t_board
ORDER BY reg_date DESC
limit #{limitStart}, #{amount}
</select>
</mapper>
Criteria(์ฟผ๋ฆฌ์ paramer์ ํ์ฉ)
// ํ๋ก ํธ์์ ํ์ด์ง ๋ฒํธ์ ํ์ด์ง ์ถ๋ ฅ ๊ฐ์๋ฅผ ๋๊ธฐ๊ธฐ ์ํ ํด๋์ค
package paging.study.domain;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter @Setter
@ToString
public class Criteria {
private int pageNum; // ํ์ด์ง ๋ฒํธ(ํ์ฌ ํ์ด์ง๊ฐ ๋ช ํ์ด์ง์ธ์ง)
private int amount; // ํ ํ๋ฉด์ ์ถ๋ ฅํ ํ์ด์ง ๊ฐ์
private int limitStart; // ์ฟผ๋ฆฌ์์ (pageNum -1) * amount ์ฌ์ฉํ๊ธฐ ์ํ ๋ณ์
// ๊ธฐ๋ณธ ๊ฐ ์ธํ
(ํ์ฌ ํ์ด์ง๋ 1, ๊ฐ์ ธ์ฌ ๋ฐ์ดํฐ๋ 10๊ฑด์ธ ๊ฒฝ์ฐ)
public Criteria() {
this.pageNum = 1;
this.amount = 10;
}
public Criteria(int pageNum, int amount) {
this.pageNum = pageNum;
this.amount = amount;
}
// ์ฟผ๋ฆฌ์์ limit 1๋ฒ ์งธ parameter๋ก ์ธ ๊ฐ(mybatis์์ getter๋ก ์ด ๊ฐ์ ์ฌ์ฉ)
public int getLimitStart() {
return this.limitStart = (pageNum - 1) * this.amount;
}
}
BoardVO
package paging.study.domain.vo;
import lombok.*;
import java.time.LocalDateTime;
@Getter @Setter
@ToString
@NoArgsConstructor
public class BoardVO {
private Long boardId;
private String title;
private String content;
private String name;
private LocalDateTime regDate;
private LocalDateTime updateDate;
public BoardVO(String title, String content, String name) {
this.title = title;
this.content = content;
this.name = name;
}
}
mapper interface
package paging.study.mapper;
import org.apache.ibatis.annotations.Mapper;
import paging.study.domain.Criteria;
import paging.study.domain.vo.BoardVO;
import java.util.List;
@Mapper
public interface BoardMapper {
List<BoardVO> findBoardListPaging(Criteria cri);
// ์ ์ฒด ์นด์ดํธ
@Select("SELECT COUNT(*) FROM t_board")
int findBoardCount();
}
service
package paging.study.service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import paging.study.domain.Criteria;
import paging.study.domain.vo.BoardVO;
import paging.study.mapper.BoardMapper;
import java.util.List;
@Service
@Slf4j
@RequiredArgsConstructor
public class BoardService {
private final BoardMapper boardMapper;
public List<BoardVO> findBoardListPaging(Criteria cri) {
return boardMapper.findBoardListPaging(cri);
}
public int findBoardCount() {
return boardMapper.findBoardCount();
}
}
controller
package paging.study.controller;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import paging.study.domain.Criteria;
import paging.study.domain.paging.PageMaker;
import paging.study.domain.vo.BoardVO;
import paging.study.service.BoardService;
import paging.study.service.ReplyService;
import java.util.List;
@Controller
@Slf4j
@RequiredArgsConstructor
public class BoardController {
private final BoardService boardService;
/**
* content list
* @param cri
* @param model
* @return
*/
@GetMapping("/board/list")
public String listPaging(@ModelAttribute("cri") Criteria cri, Model model) {
// ํ๋ฉด์์ cri๋ฅผ ๋ฐ์์ ๋ชฉ๋ก ์กฐํ ์๋น์ค ํธ์ถ์ parameter๋ก ๊ฐ์ด ๋๊น
List<BoardVO> list = boardService.findBoardListPaging(cri);
// ํ์ด์ง๋ค์ด์
ํ๋ฉด ์ฒ๋ฆฌ์ ํ์ํ ์ ์ฒด ๋ชฉ๋ก ๊ฐ์ ๊ตฌํจ
int boardCount = boardService.findBoardCount();
// model์ 2 ์ข
๋ฅ์ ๋ฐ์ดํฐ(๋ฆฌ์คํธ, ํ์ด์ง๋ค์ด์
๋ฐ์ดํฐ)๋ฅผ ๋ด์์ view์ ์ ๋ฌ
model.addAttribute("list", list);
// pageMaker์ 2๊ฐ์ parameter๋ฅผ ๋๊น
model.addAttribute("pageMaker", new PageMaker(boardCount, cri));
return "board/boardList";
}
}
ํ์ด์ง๋ค์ด์ ํ๋ฉด ์ฒ๋ฆฌ๋ฅผ ์ํ ํด๋์ค ๐
// ํ๋ก ํธ์์ ๋๊ธด Criteria๋ฅผ ์ฐธ์กฐํด์ ์ค์ ํ๋ฉด์์ ํ์ด์ง๋ค์ด์
์ฒ๋ฆฌ๋ฅผ ํ๊ธฐ ์ํ ๊ณ์ฐ์ ํ๋ ํด๋์ค
package paging.study.domain.paging;
import lombok.Getter;
import lombok.ToString;
import paging.study.domain.Criteria;
@Getter // ์ธ๋ถ์์ ๊ฐ ๋ณ๊ฒฝ ๋ถ๊ฐํ๋๋ก setter๋ ์ ์ธํ์ง ์์
@ToString
// ํ์ด์ง๋ค์ด์
ํ๋ฉด์์ ํ์ํ ๋ฐ์ดํฐ ๊ณ์ฐํ๋ ํด๋์ค
public class PageMaker {
private int startPage; //ํ์ด์ง ํ๋ฉด ํ๋จ์ ์์ ๋ฒํธ(5ํ์ด์ง๋ผ๊ณ ํ๋ฉด [1][2][3][4][5] ์ฌ๊ธฐ์ ์ ์ผ ์ฒซ ๋ฒ ์งธ ์์๋ฒํธ)
private int endPage; //ํ์ด์ง ํ๋ฉด ํ๋จ์ ๋ ๋ฒํธ(5ํ์ด์ง๋ผ๊ณ ํ๋ฉด [1][2][3][4][5] ์ฌ๊ธฐ์ ์ ์ผ ๋ ๋ฒํธ)
private boolean prev, next; // ์ด์ , ๋ค์ ์กด์ฌ ์ฌ๋ถ
private int totalCount; // ์ ์ฒด ๊ฒ์๊ธ ์
private Criteria cri; // ํ๋ก ํธ์์ ์ ๋ฌํ๋ pageNum(ํ์ฌ ํ์ด์ง), amount(์ถ๋ ฅ ํ์ด์ง) ์ ๋ฌ ์ญํ
// ๊ฒ์ฐ์์ ํ์ํ ๊ฒ ์ ์ฒด ์นด์ดํธ, ๊ทธ๋ฆฌ๊ณ ํ์ฌ ํ์ด์ง์ ํ์ด์ง ๊ฐ์
// 2๊ฐ parameter๋ฅผ ๋ฐ์์ ์๋์์ ๊ณ์ฐ ์ฒ๋ฆฌ(๊ณต์์ด๋ ์ธ์ธ ํ์๋ ์๊ณ ์ด๋ฐ์์ผ๋ก ๊ตฌํ๋ ๊ตฌ๋๋ผ๊ณ ์ดํดํ๋ฉด ๋จ)
public PageMaker(int totalCount, Criteria cri) {
this.totalCount = totalCount;
this.cri = cri;
this.endPage = (int)(Math.ceil(cri.getPageNum()/10.0)) * 10;
this.startPage = this.endPage - 9;
// ์ค์ ๋ ๋ฒํธ
int realEnd = (int)(Math.ceil((totalCount * 1.0) / cri.getAmount()));
// ๋ง์ผ 80๊ฐ์ ๋ฐ์ดํฐ๊ฐ ์์ ๋ ๋๋ฒํธ๋ 10์ด ์๋๋ผ 8์ด ๋์ด์ผ ํ๊ธฐ์ ์ค์ ๋๋ฒํธ์ ๋น๊ตํด์ ์ค์ ๋ ๋ฒํธ๋ก ์นํ
if(realEnd < this.endPage) {
this.endPage = realEnd;
}
// ์ด์ , ๋ค์
this.prev = this.startPage > 1;
this.next = this.endPage < realEn
}
}
view(thymeleaf)
<!-- ๊ฒ์๊ธ ๋ชฉ๋ก ์์ญ start -->
<div>
<table class="table table-striped">
<thead>
<tr>
<th>์์ด๋</th>
<th>์ ๋ชฉ</th>
<th>๋ด์ฉ</th>
<th>์ด๋ฆ</th>
</tr>
</thead>
<tbody>
<!-- ๊ฒ์๊ธ ๋ชฉ๋ก ๋ฃจํ ๋๋ฉฐ ํ์ -->
<tr th:each="item : ${list}">
<td th:text="${item.boardId}"></td>
<td th:text="${item.title}"></td>
<td th:text="${item.content}"></td>
<td th:text="${item.name}"></td>
</tr>
</tbody>
</table>
</div>
<!-- // ๊ฒ์๊ธ ๋ชฉ๋ก ์์ญ end -->
<!-- ๊ฒ์ํ ํ๋จ ํ์ด์ง๋ค์ด์
์์ญ start -->
<nav aria-label="Page navigation">
<ul class="pagination">
<!-- prev -->
<li class="page-item" th:if="${pageMaker.prev} == true">
<a class="page-link" th:href="@{/board/list(pageNum=${pageMaker.startPage}-1)}">Prev</a>
</li>
<!-- pageMaker์ startPage๋ถํฐ endPage๊น์ง ๋ฃจํ, aํ๊ทธ์ href์ idx๋ฅผ ๋งํฌ(get๋ฐฉ์์ผ๋ก pageNum์ ๋ถ์ฌ์) -->
<li class="page-item" id="paginate_btn" th:each="idx: ${#numbers.sequence(pageMaker.startPage, pageMaker.endPage)}" th:classappend="${pageMaker.cri.pageNum} == ${idx} ? active : null">
<a class="page-link" th:href="@{/board/list(pageNum=${idx})}" th:text="${idx}"></a>
</li>
<!-- next -->
<li class="page-item" th:if="${pageMaker.next} == true and ${pageMaker.endPage > 0}">
<a class="page-link" th:href="@{/board/list(pageNum=${pageMaker.endPage}+1)}">Next</a>
</li>
</ul>
</nav>
<!-- // ๊ฒ์ํ ํ๋จ์ ํ์ด์ง๋ค์ด์
์์ญ end -->
์ด๋ ๊ฒ ํ๋ฉด ์๋์ฒ๋ผ ๋ชป์๊ธด ํ์ด์ง๋ค์ด์ ์ฒ๋ฆฌ๊ฐ ๋ ๊ฒ์ํ ๋ชฉ๋ก์ด ํ์๋๋ค.

๋ฐ์ดํฐ๊ฐ ์ ๋์ค๋์ง ํ์ธ ํ ์๋์ฒ๋ผ ๋์์ธ์ ์ ํ๋ฉด ๋๋ค.

ํ ์คํธ๋ฅผ ์ํด ๊ธํ๊ฒ ๋ง๋ ๊ฑฐ๋ผ ์คํ์๊ฐ ์๊ฑฐ๋ ์ค๋ฅ๊ฐ ์์ ์ ์์ผ๋ ์๋ ค์ฃผ์๋ฉด ๊ฐ์ฌ๋๋ฆฌ๊ฒ ์ต๋๋ค.

'IT > development' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [jQuery]radio/checkbox ์ฒดํฌ ์ฌ๋ถ ํ์ธ (0) | 2022.11.19 |
|---|---|
| [IDE/SVN]eclipse svn branch ์์ฑ (0) | 2022.11.19 |
| [spring boot/mybatis] ์ฟผ๋ฆฌ ๋ก๊ทธ ์ ๋ ฌ ๋ฐ ๊ธฐํ(feat. log4jdbc) (0) | 2022.11.19 |
| [mybatis] map์ list๋ก ๋ฐ์์ ํ๋ฉด์ ๊ทธ๋ฆฌ๊ธฐ (0) | 2022.11.19 |
| [IDE]dbeaver ํ๊ธ ๊นจ์ง ์กฐ์น (0) | 2022.11.18 |
๋๊ธ