프로그래밍/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. 결과

마지막 페이지

 


도움 받은 글 

https://to-dy.tistory.com/90