@GetMapping("/list")
public String list(Model m, HttpServletRequest request, @ModelAttribute PageVO b) throws Exception{
/* 페이징 => 쪽나누기 코드 추가*/
int page = 1; //현재 쪽수 번호
int limit = 10; //한페이지에 보여지는 목록개수
if(request.getParameter("page")!=null) {
//get으로 전달된 쪽 번호가 있는 경우
page = Integer.parseInt(request.getParameter("page"));//전달 받은 페이지번호(쪽번호)를 정수 숫자로 바꿔서 저장시킴.
}
//예를들어 현재페이지가 3페이지면 임의의 번호값 컬럼에서 31번부터 40까지 열개목록 의 로직
b.setStartrow((page-1)*10+1);//시작행 번호(시퀀스?)
b.setEndrow(b.getStartrow()+limit-1);//끝번호
List<BoardVO> blist = this.boardService.getBoardList(b);
request.setAttribute("blist", blist);
//총 게시물 수 반환
int totalCount = this.boardService.getTotalCount();
m.addAttribute("totalCount",totalCount);
/*페이징 연산*/
int maxpage=(int)((double)totalCount/limit+0.95);//총 페이지 수
/*
자바의 자동산술법에 의해서 int limit가 double타입으로 변경이 되어져서 실수값에 나눗셈을 하면 몫과 나머지를 함께 구한다.
그러므로 1.1이 된다. 여기에 1.1+0.95 = 2.05가 된다.
이것을 (int)로 캐스팅하면 소수점을 버리고 총 페이지수가 2쪽이 된다. +0.90~0.99까지 됨.
1을 더해도 되는데 왜 0.9~0.99로 해줄까 생각할수도 있다.
위와 같이 0.90~0.99로 해주는 이유는 1을더했을때 만약 페이지가 10단위로 넘어가면 페이지가 한개 더생겨버린다.
그 중간값을 사용함.
*/
//현재 페이지에 보여질 시작 페이지
int startpage=(((int)((double)page/10+0.9))-1)*10+1;
//현재 페이지에 보여질 마지막 페이지
int endpage=maxpage; //endpage는 가장 마지막 페이지 숫자를 출력해준다.
if(endpage>startpage+10-1) endpage=startpage+10-1;
m.addAttribute("startpage",startpage);//시작페이지
m.addAttribute("endpage",endpage);//끝페이지
m.addAttribute("maxpage",maxpage);//최대페이지
m.addAttribute("page",page);//page키이름에 현재 쪽번호 저장
return "/board/list";
}
page - 현재 페이지 : startRow 시작행을 구할 때 사용됩니다 / startPage 시작 페이지를 구할 때 사용됩니다
limit - 한 페이지에 보여줄 게시글 갯수
row - limit 보여줄 게시글 갯수 limit를 정해주는 기준
startRow - sql문에 들어갈 시작행 번호 : 현재 페이지 page가 필요합니다, endRow를 구할 때 사용됩니다
endRow - sql문에 들어갈 끝행 번호 : 시작행 startRow가 필요합니다
totalCount - 총 게시글 수 : 총 페이지 maxPage를 구할때 사용됩니다
maxPage - 총 페이지 수 : ui c:if문 다음버튼 : 총 게시글 수 totalCount가 필요합니다
startPage - 현재 페이지에 보여질 시작페이지 : ui forEach 반복문의 begin -현재 페이지 page가 필요합니다
endPage - 현재 페이지를 보여줄 마지막 페이지 : ui forEach 반복문의 end - 시작페이지 startpage가 필요합니다
적용 | 필요 & 사용 | |||
page | 현재 페이지 | 시작행 startRow를 구할 때 사용 시작 페이지startPage 를 구할 때 사용 |
||
limit | 한 페이지에 보여줄 게시글 갯수 | x | ||
row | 보여줄 게시글 수 limit를 정해주는 기준 | x | ||
startRow | 시작행 번호 | sql문 | - 현재 페이지 page가 필요 - endRow를 구할 때 사용 |
|
endRow | 끝행 번호 | sql문 | - 시작행 startRow가 필요 - 보여줄 갯수 limit가 필요 |
|
totalCount | 총 게시글 수 | 총 페이지 maxPage를 구할때 사용 | ||
maxPage | 총 페이지 수 | ui c:if문 다음버튼 | 총 게시글 수 totalCount가 필요 | |
startPage | 현재 페이지에 보여질 시작페이지 | jsp의 forEach 반복문의 begin | 현재 페이지 page가 필요 | |
endPage | 현재 페이지를 보여줄 마지막 페이지 | jsp의 forEach 반복문의 end |
시작페이지 startpage가 필요 |
ROWNUM
ROWNUM 컬럼을 통한 페이지당 보여줄 게시글 갯수
한페이지에 보여줄 게시글 목록을 담아오는 쿼리문입니다.
select * from
(select ROWNUM rNum, board_no, title, content, writer, reg_date, view_cnt
from (select * from mvc_board order by board_no desc))
where rnum between #{startrow} and #{endrow};
혹은
select rnum, board_no, title, content, writer, reg_date, view_cnt from
(select ROWNUM as rNum, board_no, title, content, writer, reg_date, view_cnt
from (select * from mvc_board order by board_no desc))
where rnum between #{startrow} and #{endrow};
위 두개의 쿼리문은 페이징 처리를 하기 위해 서브쿼리문을 통해 ROWNUM과 ROWNUM의 별칭인 rNum을 각각 사용하였습니다.
ROWNUM 컬럼은 테이블에 레코드 저장시 저장된 순서에 따라 1부터 1씩증가되는 일련의 번호값 이 차례대로 저장됩니다.
이 컬럼값은 자료가 입력되는 시점에 결정되기 때문에 정렬 검색 할때 바뀌지 않게됩니다.
/*메인쿼리문*/
select * from
(서브1 from (서브2))
where rnum between #{startrow} and #{endrow};
메인 쿼리문은 (서브1 from (서브2) 쿼리문 으로 부터 모든것을 조회한다고 선언해주었으며,
where 조건절의 조건은 rNum? 이라는 알수없는 컬럼이 startrow(시작행의 번호) 부터 endrow(끝행번호) 사이의 rNum 컬럼을 기준으로 모든것을 조회합니다.
이렇다함은 rNum이라는 컬럼이 어찌되었든 일단은 존재한다는 뜻이 됩니다. (가상의 컬럼이며, 서브쿼리문을 통해 만들어질 예정입니다.)
이때의 rNum은 ROWNUM 이라는 가상컬럼의 별칭이며
ROWNUM 컬럼은 서브쿼리문에서 가상으로 행을 추가하여
번호값을 부여해주는 기능을 수행 하게 됩니다.
다시 쿼리문으로 돌아오면
/*서브 쿼리문 1 */
select ROWNUM rNum, board_no, title, content, writer, reg_date, view_cnt
from
1차 서브 쿼리문이 실행됩니다. 1차 쿼리문에서 ROWNUM과 그 별칭 rNum을 선언함으로써 가상의 rownum컬럼을 부여하고 rum이라는 별칭을 주게됩니다.
이때 기본적으로 ROWNUM 은 1부터 1씩증가되는 번호값이 부여되기 때문에 rNum컬럼에 오름차순으로 번호값이 부여됩니다.
/*서브쿼리문 2*/
select * from mvc_board order by board_no desc
이어서 2차 서브 쿼리문이 실행되고 수행된 수행결과는 mvc_board테이블의 모든 컬럼을 조회하여 내림차순으로 정렬하게 됩니다.
이것을 역순으로 읽게된다면
[3 [2 [1 mvc_board 테이블의 모든것을 조회하여 역순으로 정렬한 후 1]
정렬된 결과값으로부터 board_no, title, content, writer, reg_date, view_cnt컬럼을 조회하고, 동시에 ROWNUM 가상의 컬럼을 만들고 별칭 rnum을 줍니다 2]
추가 및 조회된 컬럼결과값들로 부터 (결과값은 한 행으로 존재하기때문에 행을기준으로 다시 검색이 가능합니다.)
한번 더 모든것을 조회하며 이때 조건은 1차 서브쿼리문에서 만들어진 ROWNUM가상컬럼인 rnum 컬럼을 기준으로 시작행번호부터 끝행번호까지 조회를 합니다. 3]
public class PageVO {
private Integer startRow; //페이지에 보여줄 첫행
private Integer endRow; //끝 행의 갯수
public Integer getStartRow() {
return startRow;
}
public void setStartRow(Integer startRow) {
this.startRow = startRow;
}
public Integer getEndRow() {
return endRow;
}
public void setEndRow(Integer endRow) {
this.endRow = endRow;
}
}
@GetMapping("/list")
public String list(Model m, HttpServletRequest request, @ModelAttribute PageVO b) throws Exception{
/* 페이징 => 쪽나누기 코드 추가*/
int page = 1; //현재 쪽수 번호
int limit = 10; //한페이지에 보여지는 목록개수
if(request.getParameter("page")!=null) {
//get으로 전달된 쪽 번호가 있는 경우
page = Integer.parseInt(request.getParameter("page"));//전달 받은 페이지번호(쪽번호)를 정수 숫자로 바꿔서 저장시킴.
}
//예를들어 현재페이지가 3페이지면 임의의 번호값 컬럼에서 31번부터 40까지 열개목록을 구하는 로직
b.setStartrow((page-1)*10+1);//시작행 번호(시퀀스?)
b.setEndrow(b.getStartrow()+limit-1);//끝번호
List<BoardVO> blist = this.boardService.getBoardList(b);
request.setAttribute("blist", blist);
return "/board/list";
}
//총 게시물 수 반환
int totalCount = this.boardService.getTotalCount();
m.addAttribute("totalCount",totalCount);
/*페이징 연산*/
int maxpage=(int)((double)totalCount/limit+0.95);//총 페이지 수
/*
자바의 자동산술법에 의해서 int limit가 double타입으로 변경이 되어져서 실수값에 나눗셈을 하면 몫과 나머지를 함께 구한다.
그러므로 1.1이 된다. 여기에 1.1+0.95 = 2.05가 된다.
이것을 (int)로 캐스팅하면 소수점을 버리고 총 페이지수가 2쪽이 된다. +0.90~0.99까지 됨.
1을 더해도 되는데 왜 0.9~0.99로 해줄까 생각할수도 있다.
위와 같이 0.90~0.99로 해주는 이유는 1을더했을때 만약 페이지가 10단위로 넘어가면 페이지가 한개 더생겨버린다.
그 중간값을 사용함.
*/
//현재 페이지에 보여질 시작 페이지
int startpage=(((int)((double)page/10+0.9))-1)*10+1;
//현재 페이지에 보여질 마지막 페이지
int endpage=maxpage; //endpage는 가장 마지막 페이지 숫자를 출력해준다.
if(endpage>startpage+10-1) endpage=startpage+10-1;
m.addAttribute("startpage",startpage);//시작페이지
m.addAttribute("endpage",endpage);//끝페이지
m.addAttribute("maxpage",maxpage);//최대페이지
m.addAttribute("page",page);//page키이름에 현재 쪽번호 저장
<!-- 페이징 처리 부분 -->
<ul class="pagination justify-content-center">
<!-- 이전버튼 -->
<!-- 현재 페이지가 1보다 크다면 이전버튼을 보여줌 -->
<c:if test="${page>1}">
<li class="page-item">
<a class="page-link" href="/board/list?page=${page-1}&row=${row}">이전</a>
</li>
</c:if>
<!-- 쪽번호 -->
<c:forEach var="a" begin="${startpage}" end="${endpage}" step="1">
<li class="page-item">
<a href="/board/list?page=${a}&row=${row}" class="page-link">${a}</a>
</li>
</c:forEach>
<!-- 다음버튼 -->
<%--현재 페이지가 총 페이지 미만일 때 다음버튼을 보여줌--%>
<c:if test="${page < maxpage}">
<li class="page-item">
<a class="page-link" href="/board/list?page=${page+1}&row=${row}">다음</a>
</li>
</c:if>
</ul>
<!-- 페이징 처리 끝 -->
쪽번호를 1부터 10까지 11부터 20까지 21 부터 30까지 반복적으로 10개를 보여주고싶다면
<!-- 쪽번호 -->
<c:forEach var="a" begin="${startpage}" end="${endpage}" step="1">
<li class="page-item">
<a href="/board/list?page=${a}&row=${row}" class="page-link">${a}</a>
</li>
</c:forEach>
<c:forEach> 문을 통해서 현재 눌려있는 page를 기반으로 시작페이지와 끝페이지를 지정해주며 그 범위내에서 1씩증가하여 li갯수를 만들어내며, 변수a를 지정하여 1회돌때 1페이지 2회돌때 2페이지 3회돌때 3페이지로 페이지를 변경시켜 지정해둔 startpage와 endpage또한 페이지가 넘어갈때 유동적으로 증가할수있도록 구현합니다.
/*페이징 연산*/
int maxpage=(int)((double)totalCount/limit+0.95);//총 페이지 수
//현재 페이지에 보여질 시작 페이지
int startpage=(((int)((double)page/10+0.9))-1)*10+1;
//현재 페이지에 보여질 마지막 페이지
int endpage=maxpage; //endpage는 가장 마지막 페이지 숫자를 출력해준다.
if(endpage>startpage+10-1) endpage=startpage+10-1;
이것은 startpage와 endpage에 대한 로직이 page의 수에 영향을 받도록 page를 기반으로 구현이되있기 때문입니다.
<!-- 이전버튼 -->
<!-- 현재 페이지가 1보다 크다면 이전버튼을 보여줌 -->
<c:if test="${page>1}">
<li class="page-item">
<a class="page-link" href="/board/list?page=${page-1}&row=${row}">이전</a>
</li>
</c:if>
<!-- 다음버튼 -->
<%--현재 페이지가 총 페이지 미만일 때 다음버튼을 보여줌--%>
<c:if test="${page < maxpage}">
<li class="page-item">
<a class="page-link" href="/board/list?page=${page+1}&row=${row}">다음</a>
</li>
</c:if>
'SpringFramework > Board게시판' 카테고리의 다른 글
미완성 [Transaction]게시물을 읽으면 조회수가 증가되는 로직 및 호출위치 (0) | 2020.09.08 |
---|---|
새로 생성한 게시물 제목에 new 마크 붙히기 (0) | 2020.09.08 |