Git · 코드 기록

Spring 페이징처리하기

짱코딩러 2022. 10. 27. 20:54

페이징 준비물

현재 페이지 번호 = pageNum

페이지마다 띄워줄 게시글 갯수 = amount 

(화면에 뜨는 페이지 번호 중에서) 맨 앞 페이지 번호 = startPage

(화면에 뜨는 페이지 번호 중에서) 맨뒤 페이지 번호 = endPage

이전 페이지 존재 유무 = prev

다음 페이지 존재 유무 = next

전체 게시글 수 = total

 

1.페이지(pageNum)마다 일정량(amount)의 게시글을 가져오는 쿼리 작성

예를 들어, 글을 10개씩 띄워준다고 할 때 4페이지를 받았으면

서브쿼리문에서는 (4*10)1~40번째 글을 select하고,

그 40개의 글중에서 (3*10)1~30번째 글을 제외한 31~40번째 글을 내림차순으로 select해줌!

	<select id="getListWithPaging" resultType="com.wine.model.NoticeVO">
	<![CDATA[
		select noticeno, subject, id, indate, count
		from(select /*+INDEX_DESC(notice SYS_C007844)*/
				rownum rn, noticeno, subject, id, indate, count
			from notice
			where rownum<= #{pageNum} * #{amount})
		where rn > (#{pageNum}-1) * #{amount}
	]]>
	</select>

 

2. 전체 게시글 수(total) 구하는 쿼리 작성

	<select id="pageTotal" resultType="int">
		select count(*) from notice where noticeno > 0
	</select>

 

3. 1.에서의 쿼리문에 쓰이는 조건값을 담을 Criteria(DTO) 클래스 생성

@Data
public class Criteria {

	private int pageNum;
	private int amount;
	private int prodno;
	
	public Criteria() {
		this(1,5);
	}
	public Criteria(int pageNum, int amount) {
		this.pageNum = pageNum;
		this.amount = amount;
	}
}

 

4. view에 전달해줄 값을 담을 PageDTO 클래스 생성

@Data
public class PageDTO {
	//맨처음 페이지 번호
	private int startPage;
	//맨끝 페이지 번호
	private int endPage;
	//이전 페이지, 다음 페이지 (있으면 true)
	private boolean prev, next;
	
	//전체 게시글 번호
	private int total;
	//현재 페이지 번호, 띄워줄 글 갯수
	private Criteria cri;
	
	public PageDTO(Criteria cri, int total) {
		this.cri = cri;
		this.total = total;
		//현재 페이지 번호를 올림처리해서 마지막 번호를 지정
		//ex.현재 페이지가 12페이지면 1.2(ceil)=>2에서 다시 10을 곱해 마지막 페이지는 20으로 정해짐.
		//수정함 => 6페이지면 0.6이 1로되고 다시 5를 곱해서 5
		this.endPage=(int)(Math.ceil(cri.getPageNum()/5.0))*5;
		//시작 페이지
		//ex. 20(마지막페이지)-9= 11로 시작하게 됨.
		this.startPage = this.endPage-4;
		//마지막에 뿌려질 페이지번호(더이상 띄워줄 글이 없을 때는 번호가 멈춰야하니까)
		//ex. 전체 글이 253개이고, 한 페이지당 10글씩 띄워준다고 했을 때 253.0에 10을 나누면 25.3이고 올림하면 26 
		int realEnd = (int)(Math.ceil((total*1.0)/cri.getAmount()));
		
		//마지막 페이지(예를들면 30일때)가 찐마지막 페이지(26)보다 크면 페이지 바꿔줌
		if(realEnd <this.endPage) {
			this.endPage = realEnd;
		}
		
		//이전 페이지는 시작 번호보다 크다.
		this.prev = this.startPage > 1;
		//다음 페이지는 찐마지막페이지보다 작다.
		this.next = this.endPage < realEnd;
	}
}

 

5. interface NoticeMapper

public List<NoticeVO> getListWithPaging(Criteria cri);
public int pageTotal(Criteria cri);

 

6.NoticeServiceImpl implements NoticeService

	@Override
	public List<NoticeVO> getList(Criteria cri) {
		return mapper.getListWithPaging(cri);
	}
    
	@Override
	public int getTotal(Criteria cri) {
		return mapper.pageTotal(cri);
	}

 

7.NoticeController

	@RequestMapping("/notice")
	public void notice(Criteria cri, Model model) {
		model.addAttribute("noticeList", nService.getList(cri)); //게시글 값
		int total = nService.getTotal(cri);
		model.addAttribute("pageMaker", new PageDTO(cri,total,1));//페이징 값
	}

 

8.notice.jsp

<!-- 현재 11~20페이지라고 가정했을 때 -->
<!-- 이전 페이지가 있으면 10페이지로 이동 (1~10페이지로 바꿔줌) -->
<c:if test="${pageMaker.prev}">
   <a href="${pageMaker.startPage -1}">이전</a>
</c:if>
<!-- 11번부터 20번까지 num을 뿌려줌. 현재페이지(pageNum)은 class 붙여줌 -->
<c:forEach var="num" begin="${pageMaker.startPage}" end="${pageMaker.endPage}">
   <a href="${num}"><span class="${pageMaker.cri.pageNum == num ? 'bold':''}"> ${num} </span></a>
</c:forEach>
<!-- 다음 페이지가 있으면 21페이지로 이동 (21~30페이지로 바꿔줌) -->				
<c:if test="${pageMaker.next}">
   <a href="${pageMaker.endPage +1}">다음</a>
</c:if>

 

8-1.값을 넘겨주기 위해 페이지에 저장해둔다.

<form id='actionForm' action="/notice/notice" method='get'>
   <input type='hidden' name='pageNum' value='${pageMaker.cri.pageNum}'>
   <input type='hidden' name='amount' value='${pageMaker.cri.amount}'>
</form>

 

<script>
$(document).ready(function(){
	var actionForm = $('#actionForm');
	$("#pageBtn a").on("click",function(e){
		e.preventDefault();
        
		actionForm.find("input[name='pageNum']").val($(this).attr("href"));
		actionForm.submit();
	});
});
</script>