프로그래밍/Java
[Java] 게시판 페이징 처리
프로그래민구찌
2021. 5. 20. 15:12
1. SQL : LIMIT
- LIMIT을 사용하면 특정페이지의 게시글의 리스트를 불러올 수 있다.
SQL > select * from board
> order by id desc
> limit 0, 5;
SQL > select * from board
> order by id desc
> limit 5, 5;
SQL > select * from 테이블명
> order by 게시글 번호 desc
> limit 시작 행, 출력할 갯수;
2. 특정 페이지 조회를 위한 Criteria 클래스
- 게시글 조회 쿼리에 전달될 파라미터를 담게 될 클래스
package com.cos.blog.model;
// 특정 페이지 조회를 위한 Criteria클래스
public class Criteria {
private int page; // 현재 페이지 번호
private int perPageNum; // 한 페이지당 보여줄 게시글의 갯수
public int getPageStart() { // 특정 페이지의 게시글 시작 번호, 게시글 시작 행 번호
// 현재 페이지의 게시글 시작 번호 = (현재 페이지 번호 - 1) * 페이지당 보여줄 게시글 갯수
return (this.page-1)*perPageNum;
}
public Criteria() {
this.page = 1;
this.perPageNum = 5;
}
public int getPage() {
return page;
}
public void setPage(int page) {
if(page <= 0) {
this.page = 1;
} else {
this.page = page;
}
}
public int getPerPageNum() {
return perPageNum;
}
public void setPerPageNum(int pageCount) {
int cnt = this.perPageNum;
if(pageCount != cnt) {
this.perPageNum = cnt;
} else {
this.perPageNum = pageCount;
}
}
}
3. 게시판 페이징을 처리하는 PageMaker 클래스
- 페이징에 관련된 버튼들을 만드는 기능을 하는 클래스
package com.cos.blog.model;
public class PageMaker {
private Criteria cri;
private int totalCount; // 총 게시글 수
private int startPage;
private int endPage; // 화면에 보여질 마지막 페이지 번호, 끝 페이지 번호
private boolean prev;
private boolean next;
private int displayPageNum = 5; // 화면 하단에 보여지는 페이지 버튼의 수
public Criteria getCri() {
return cri;
}
public void setCri(Criteria cri) {
this.cri = cri;
}
public int getTotalCount() {
return totalCount;
}
public void setTotalCount(int totalCount) {
this.totalCount = totalCount;
// 총 게시글 수를 셋팅할때 calcData()메서드를 호출하여 페이징 관련 버튼 계산을 한다
calcData();
}
// 페이징의 버튼들을 생성하는 계산식을 만들었다. 끝 페이지 번호, 시작 페이지 번호, 이전, 다음 버튼들을 구한다.
private void calcData() {
endPage = (int) (Math.ceil(cri.getPage() / (double) displayPageNum) * displayPageNum);
// 시작 페이지 번호 = (끝 페이지 번호 - 화면에 보여질 페이지 번호의 갯수) + 1
startPage = (endPage - displayPageNum) + 1;
if(startPage <= 0) startPage = 1;
int tempEndPage = (int) (Math.ceil(totalCount / (double) cri.getPerPageNum()));
if (endPage > tempEndPage) {
endPage = tempEndPage;
}
// 이전 버튼 생성 여부 = 시작 페이지 번호 == 1 ? false : true
prev = startPage == 1 ? false : true;
// 다음 버튼 생성 여부 = 끝 페이지 번호 * 한 페이지당 보여줄 게시글의 갯수 < 총 게시글의 수 ? true: false
next = endPage * cri.getPerPageNum() < totalCount ? true : false;
}
public int getStartPage() {
return startPage;
}
public void setStartPage(int startPage) {
this.startPage = startPage;
}
public int getEndPage() {
return endPage;
}
public void setEndPage(int endPage) {
this.endPage = endPage;
}
public boolean isPrev() {
return prev;
}
public void setPrev(boolean prev) {
this.prev = prev;
}
public boolean isNext() {
return next;
}
public void setNext(boolean next) {
this.next = next;
}
public int getDisplayPageNum() {
return displayPageNum;
}
public void setDisplayPageNum(int displayPageNum) {
this.displayPageNum = displayPageNum;
}
}
4. BoardController에서 처리 방법과 JSP
@GetMapping({"","/"})
public String index(String search, Model model, Criteria cri) {
PageMaker pageMaker = new PageMaker();
pageMaker.setCri(cri);
pageMaker.setTotalCount(boardService.게시글갯수()); // 총 게시글의 수
List<Board> boards = boardService.현재페이지(cri);
model.addAttribute("curPageNum", cri.getPage());
model.addAttribute("pageMaker", pageMaker);
model.addAttribute("boards", boards);
return "index"; // viewResolver 작동!!
}
- index.jsp
<ul class="pagination justify-content-center" style="margin-top:20px;">
<c:choose>
<c:when test="${pageMaker.prev}">
<li class="page-item"><a class="page-link" href="?page=${pageMaker.startPage-1}">Previous</a></li>
</c:when>
<c:otherwise>
<li class="page-item disabled"><a class="page-link" href="?page=${pageMaker.startPage-1}" disabled>Previous</a></li>
</c:otherwise>
</c:choose>
<c:forEach begin="${pageMaker.startPage}" end="${pageMaker.endPage}" var="pageNum">
<c:choose>
<c:when test="${pageNum == curPageNum}">
<li class="page-item active">
<a class="page-link" href="?page=${pageNum}">${pageNum}</a>
</li>
</c:when>
<c:otherwise>
<li class="page-item">
<a class="page-link" href="?page=${pageNum}">${pageNum}</a>
</li>
</c:otherwise>
</c:choose>
</c:forEach>
<c:choose>
<c:when test="${pageMaker.next && pageMaker.endPage > 0}">
<li class="page-item"><a class="page-link" href="?page=${pageMaker.endPage + 1}">Next</a></li>
</c:when>
<c:otherwise>
<li class="page-item disabled"><a class="page-link" href="?page=${pageMaker.endPage + 1}">Next</a></li>
</c:otherwise>
</c:choose>
</ul>
5. BoardService 단의 게시글갯수 메서드와 현재페이지 메서드
@Transactional
public int 게시글갯수() {
return (int)boardRepository.count(); // jpa에 내장되있는 count()메서드 - 게시글 갯수
}
@Transactional
public List<Board> 현재페이지(Criteria cri){
return boardRepository.page(cri.getPageStart(), cri.getPerPageNum());
}
6. BoardRepository 단의 쿼리문으로 현재페이지의 리스트 가져오기
public interface BoardRepository extends JpaRepository<Board, Integer> {
List<Board> findByTitleContaining(String search);
@Query(value= "SELECT * FROM board ORDER BY id DESC LIMIT ?, ?", nativeQuery = true)
List<Board> page(int startPage, int pageSize);
}
7. 결과
도움 받은 글