게시판9) 게시판 페이징
in Web Dev on Java Spring
- 1000개의 글이 있다고 쳤을 때, 이 글을 한 페이지에 보여주는 것 보다 여러 페이지에 보여주는 것이 훨씬 정보를 쉽게 전달할 수 있다. 아래와 같이 페이지를 나누고, 글 번호도 그에 따라 줘보도록 한다.
페이징 개념
한 페이지에 내가 20 개의 글을 보여주고 싶을 수도 있고, 10개의 글을 보여주고 싶을 수도 있다. 이것을 countPerPage 라고 하자. 이걸 기준으로 페이징을 시작할 수 있다.
과정
- countPerPage 를 정한다. (나는 10으로 정했다)
- totalRecordCount 는 record가 총 몇개 있는지 읽어온다.
- totalPageCount는 totalRecordCount + (countPerPage-1) 를 countPerPage 로 나누면 구할 수 있다. 여기서 만약 “totalRecordCount/countPerPage” 만 하면, 나머지 글이 담길 페이지가 없어서 안된다. 그냥 한페이지를 더해준다고 했을 때 나머지가 0일 때 불필요한 페이지가 생생된다. 그래서 저렇게 해준다.
- currentPage 는 현재 페이지가 몇쪽인지 알려준다.
- 현재 페이지의 srow(글 시작번호)와 erow(글 끝번호)는 currentPage와 countPerPage를 이용해 구할 수 있다.
- 만약 이 과정이 어렵게 생각된다면, 그냥 간단한 숫자를 대입해보면 쉽게 이해될 것이다.
- 11개의 글이 있다고 할 때 totalRecordCount =11 이다.
- 한페이지에 5개의 글을 넣고싶다고 하면 countPerPage=5 가된다. 총 페이지는 (11+5-1)/5 = 3 라 totalPageCount=3이다. (1페이지 : 1개글, 2페이지: 5개글, 3페이지: 5개글).
- currentPage=2 **라면, 행의 시작값은 (2-1)*5+1이 된다. **srow = 6
- erow =10이다.
변수들은 다음과 같이 생성된다. (아래서 좀 더 자세히 볼 것이다.)
countPerPage = 10;
totalRecordCount = repository.getBoardCount(searchItem,searchWord);
totalPageCount = (totalRecordCount+countPerPage-1)/countPerPage;
currentPage
srow = 1+(currentPage-1)*countPerPage;
erow = currentPage*countPerPage;
페이징 코드
controller
@RequestParam으로, currentPage에 대한 정보가 전달되지 않을 때는 디폴트로 1을 준다. 인덱스에서 boardList로 넘어올 때 항상 1페이지로 되어있다.
@RequestParam(value="currentPage",defaultValue="1") int currentPage
변수는 위에서 설명한 대로 만든다. 그리고 model에 저장해서 jsp에서 꺼내쓸 수 있게 해준다.
int totalRecordCount = repository.getBoardCount(searchItem,searchWord); int countPerPage = 10; int totalPageCount = (totalRecordCount+countPerPage-1)/countPerPage; //srow,erow는 jsp 에서는 안 쓰이고,DB에서 record 가져올 때 쓰임 int srow = 1+(currentPage-1)*countPerPage; int erow = currentPage*countPerPage; model.addAttribute("currentPage",currentPage); model.addAttribute("totalRecordCount",totalRecordCount); model.addAttribute("totalPageCount",totalPageCount);
전체 코드
@RequestMapping("/boardlist") public String boardList( @RequestParam(value="currentPage",defaultValue="1") int currentPage, @RequestParam(value="searchItem", defaultValue ="title") String searchItem, @RequestParam(value="searchWord", defaultValue ="") String searchWord, Model model) { int totalRecordCount = repository.getBoardCount(searchItem,searchWord); int countPerPage = 10; int totalPageCount = (totalRecordCount+countPerPage-1)/countPerPage; int srow = 1+(currentPage-1)*countPerPage; int erow = currentPage*countPerPage; List<Board> list = repository.boardList(srow,erow,searchItem,searchWord);//글 목록 조회 model.addAttribute("list",list); model.addAttribute("currentPage",currentPage); model.addAttribute("searchItem", searchItem); model.addAttribute("searchWord", searchWord); model.addAttribute("totalRecordCount",totalRecordCount); model.addAttribute("totalPageCount",totalPageCount); return "board/boardList"; }
repository
DB에서 srow ~ erow 까지의 정보를 요청하고 가져와준다.
public List<Board> boardList(int srow, int erow, String searchItem, String searchWord) { Map<String,Object> map = new HashMap<String,Object>(); BoardMapper mapper = session.getMapper(BoardMapper.class); map.put("searchItem",searchItem); map.put("searchWord",searchWord); map.put("srow",srow); map.put("erow",erow); List<Board> list = mapper.boardList(map); return list; }
boardMapper.xml
좀 복잡하다!
DB에서 제공해주는 ROWNUM이 우리가 arg로 전달한 srow와 erow 범위에 있으면 데이터를 가져오려고 한다 . ROWNUM은 DB가 기본으로 제공해주는 데이터이므로, 우리 테이블 열네임에는 포함되어있지않다. 그래서 그것을 우리 테이블 열에 포함시키기 위해 아래와 같은 작업을 해준다.
SELECT ROWNUM as nu, temp.* FROM ( SELECT boardseq, userid, title, message, to_char(regdate, 'YYYY-MM-DD') as regdate, hitcount, originalfile, savedfile FROM board) temp
이렇게 하면, ROWNUM과 BOARDTABLE의 정보를 가진 TEMP 테이블이 생성된다.
그 런 데! 이렇게 해서 바로 WHERE절을 쓰면 안된다!
SELECT * FROM TEMP WHERE ROWNUM >= 1 AND ROWNUM <=10 일케하면 1~10까지는 나오지만,
SELECT * FROM TEMP WHERE ROWNUM >= 11 AND ROWNUM <=20 은 안 나온다.
왜냐면, ROWNUM은 동적 데이터라서 항상 1번부터 나타난다.
해결방법은 간단하다. SELECT * FROM 으로 감싸서 하나의 테이블로 정착? 시켜버리면 된다.
그리고 <= 이거 먹히지 않는다. 태그로 알아먹어서.. 그래서
> < 로 써줘야한다.
대충 전체 코드
<select id="boardList" resultType="Board" parameterType="map"> SELECT * FROM ( SELECT ROWNUM as nu, temp.* FROM ( SELECT boardseq, userid, title, message, to_char(regdate, 'YYYY-MM-DD') as regdate, hitcount, originalfile, savedfile FROM board) temp ) WHERE nu >= #{srow} AND nu <= #{erow} </select>
boardList.jsp
- 위 DB에서 가져온 자료들은 controller에서 list에 저장된다.
list에는 해당 페이지에 들어가야할 board 객체들이 들어있다.
- 예를들어 2페이지라면, DB에서 11~20의 ROWNUM을 가지는 board가 list에 들어가있다.
<c:forEach var= "board" items="${list}" varStatus="status">
<tr>
<td>${ status.count + (currentPage-1)*10}</td>
</tr>
</c:forEach>
페이지 번호
쉬우니 설명 생략!
<div class = "navigator"> 전체 글개수 : ${totalRecordCount }<br> ◁ <c:forEach var ="page" begin="1" end = "${totalPageCount }"> <c:if test = "${currentPage eq page}"> <span style = "color : red; font-weight: bold">"${page}"</span> </c:if> <c:if test = "${currentPage ne page}"> <a href = "boardlist?currentPage=${page }¤tPage=${page}&searchItem=${ searchItem}&searchWord=${searchWord}"> ${page} </a> </c:if> </c:forEach> ▷ </div>
◇ Spring 게시판 포스팅 시리즈 ◇