본문 바로가기
개발자/자바 & 스프링

Spring, mybatis 페이징 처리 / 자바 스프링 페이징

by mansfield 2023. 2. 14.
반응형

페이징 처리 VO : 롬복을 이용하여 생성자, Getter, Setter 생성

@Data
@AllArgsConstructor
@NoArgsConstructor
public class BoardPageData {
	
	private ArrayList<Board> list;	//게시글 리스트
	private String pageNavi;	//페이지 네비게이션  1, 2, 3, 4, 5, > >>
	
}

@AllArgsConstructor
@NoArgsConstructor
@Data
public class Board {
	
	private int boardNo;
	private String boardTitle;
	private String boardContent;
	private String boardWriter;
	private String boardDate;
	
	private ArrayList<FileVO> fileList;
}

페이징 처리 Service 단 

	public BoardPageData selectBoardList(int reqPage) {
		//reqPage : 현재 페이지
		//페이징처리
		//한 페이지당 보여줄 게시물 수 : 10개
		int numPerPage = 10;
		
		//reqPage 1 -> 1번 ~ 10번 게시물, reqPage 2 -> 11번 ~ 20번 게시물
		//해당 페이지 요청 마지막 번호 
		int end = reqPage * numPerPage;
		
		//해당 페이지 첫번째 게시물 번호
		int start = end - numPerPage + 1;
		
		//계산한 start, end를 이용해서 게시물 목록 조회 
        	//mybatis 사용, 2개의 데이터를 한번에 보내기 위해 HashMap 사용
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("start", start);
		map.put("end", end);
		
		ArrayList<Board> list = dao.selectBoardList(map);
		
		//pageNavi 작성 시작
		//전체 게시물의 수를 DB에서 조회한다 -> 총 몇 페이지인지 계산하기 위해서 
		int totalCount = dao.selectBoardCount();
		
		//구해온 전체 게시물 수를 통해 전체 페이지 수 계산
		int totalPage = 0;
		if(totalCount % numPerPage == 0) {
			//전체 게시글과 한페이지당 보여줄 게시글의 나머지 연산이 0인 경우 
			totalPage = totalCount/numPerPage;
		}else {
			//전체 게시글과 한페이지당 보여줄 게시글의 나머지 연산이 0이 아닌 경우 
			//예를 들어 95개의 게시글이 있을 때 10개씩 9개의 페이지 이외에도 5개의 게시글을 보여줘야하니 추가로 1페이지 생성
			totalPage = totalCount/numPerPage + 1;
		}
		
		//페이지 네비게이션 길이 (한번에 몇 페이지의 숫자까지 보여줄 것인지)
		int pageNaviSize = 5;
		
		//페이지 네비 시작번호 ver.1 (페이지가 6페이지일 때 4,5,6,7,8 페이지가 보임) 같이 이동
		/*	int pageNo = 1;
		 *	if(reqPage>3) {
		 *	//페이지가 3페이지보다 작을때 -2를 하면 -1, 0 페이지가 나오기 때문
		 *		pageNo = reqPage - 2;
		 *	}
		*/
		
		//페이지 네비 시작번호 ver.2 (몇 페이지를 클릭하던 해당 페이지네비 길이의 숫자 고정, 다음을 눌러야 다른 페이지 네비의 숫자가 보여짐)
		// 1 ~ 5 페이지 요청시 -> 	1 2 3 4 5
		// 6 ~ 10페이지 요청시 -> 	6 7 8 9 10
		//페이지 네비게이션 시작번호 계산
		int pageNo = ((reqPage-1)/pageNaviSize)*pageNaviSize + 1;
		
		//페이지 네비게이션 제작  시작 
		String pageNavi = "";
		//이전버튼 : 1페이지가 아닐때만 만듬
		if(pageNo != 1) {
			pageNavi += "<a href='/boardList.do?reqPage="+(pageNo-1)+"'>";
			pageNavi += "<span>◀</span>";
			pageNavi += "</a>";
		}
		//페이지 숫자
		for(int i=0; i<pageNaviSize; i++) {
			if(pageNo == reqPage) {
				//페이지 숫자와 현재 페이지가 같은 경우 : 굵게보여줌
				pageNavi += "<a href='boardList.do?reqPage="+pageNo+"'>";
				pageNavi += "<strong>" + pageNo + "</strong>";
				pageNavi += "</a>";
			}else {
				pageNavi += "<a href='boardList.do?reqPage="+pageNo+"'>";
				pageNavi += pageNo;
				pageNavi += "</a>";
			}
			pageNo++;
			if(pageNo > totalPage) {
				//만든 페이지 숫자가 최대 페이지보다 크면 그만만듬
				break;
			}
		}
		//다음버튼 : 전체 페이지보다 작을때만 만듬
		if(pageNo <= totalPage) {
			//위의 for문에서 pageNo++로 숫자가 1 증가해서 나왔으므로 따로 (pageNo+1)을 해주지 않아도 됨
			pageNavi += "<a href='/boardList.do?reqPage="+pageNo+"'>"; 
			pageNavi += "<span>▶</span>";
			pageNavi += "</a>";
		}
		System.out.println(pageNavi);
		
		//컨트롤러에 페이지 정보 및 리스트 전달 : BoardPageData객체 이용
		BoardPageData bpd = new BoardPageData(list, pageNavi);
		
		return bpd;
	}

페이징 처리 DAO 단  > selectBoardList 

@Repository
public class BoardDao {
	
	@Autowired
	private SqlSessionTemplate sqlSession;

	public ArrayList<Board> selectBoardList(HashMap<String, Object> map) {
		
		List list = sqlSession.selectList("selectBoardList", map);
		
		return (ArrayList<Board>)list;
	}

페이징 처리 mybatis > boardSQL.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" >
<mapper namespace="boardDao">
  
  <select id="selectBoardList" parameterType="map" resultType="board">
  	select * from
        (select rownum as rnum, b.* from
            (select 
                board_no as boardNo,
                board_title as boardTitle,
                board_writer as boardWriter,
                board_date as boardDate
             from board order by board_no desc)b)
    where rnum between #{start} and #{end}    
  </select>

1. select board_no ~~ from board order by board_no desc 

board 테이블의 board_no 를 기준으로 내림차순 정렬 (최근 게시글이 먼저 조회되도록) 

board_no as boardNo => 데이터베이스에는 컬럼명이 board_no로 되어있지만 VO에는 boardNo로 되어있기 때문에 as 를 사용하여 매치시켜줌

2. select rownum as rnum, b.* from (select board_no ~~ from board order by board_no desc)b 

조회하고자 하는 데이터인 (select board_no ~~ from board order by board_no desc) 에 b라는 별칭을 붙이고 b를 하나의 테이블로 만들기 위해 서브쿼리 사용. 

게시글 번호가 중간에 비어있을 수도 있음. 게시글 번호에 상관없이 한 페이지에 동일한 갯수의 게시글을 보여주기 위해 rownum 함수 사용. => 조회된 결과에 rownum 함수가 새로운 번호를 붙여줌. 

3. select * from (select rownum as rnum, b.* from(select board_no ~~ from board order by board_no desc)b) where rnum between #{start} and #{end} 

원하는 자료를 조회했고 게시판, 페이징 처리를 위한 게시글에 고유의 번호를 붙였음. 서브쿼리를 이용하여 감싼 후 조건절을 붙여줌.

조건절에 HashMap으로 넘어온 한 페이지의 시작 게시글 번호와 끝 게시글 번호를 넣어줌. => where rnum between #{start} and #{end} 


페이징 처리 Controller 단

@Controller
public class BoardController {
	
	@Autowired
	private BoardService service;
	
	@RequestMapping("/boardList.kh")
	public String boardList(int reqPage, Model model) {
		
		BoardPageData bpd = service.selectBoardList(reqPage);
		
		model.addAttribute("list", bpd.getList());
		model.addAttribute("pageNavi", bpd.getPageNavi());
		model.addAttribute("reqPage", reqPage);
		
		return "board/boardList"; 
		
	}

BoardPageData VO에 담긴 정보들을 화면으로 보내주기 위해 model.addAttribute 사용. 현재페이지인 reqPage도 함께 보내줌. 


 

페이징처리 jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>      
    
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	
	<h1>게시판</h1>
	<hr>
	<c:if test="${!empty sessionScope.m }">
		<a href="/boardWriteFrm.do">글 작성하기</a>
	</c:if>
	<table border="1">
		<tr>
			<th>번호</th><th>제목</th><th>작성자</th><th>작성일</th>
		</tr>
		<c:forEach items="${list }" var="b" varStatus="i">
			<tr>
				<%-- DB의 게시글 번호가 아니라 화면에만 보여줄 번호 --%>
				<td>${(reqPage-1)*10 + i.count }</td>
				<td><a href="/boardView.do?boardNo=${b.boardNo }">${b.boardTitle }</a></td>
				<td>${b.boardWriter }</td>
				<td>${b.boardDate }</td>
			</tr>
		</c:forEach>
		<tr>
			<th colspan="4">${pageNavi }</th>
		</tr>
		
	</table>	
</body>
</html>

 

300x250

댓글