테이블
create TABLE TBL_MEMBER( mid NUMBER PRIMARY KEY, userid VARCHAR2(100), userpw VARCHAR2 (100) NOT NULL, username VARCHAR2 (50) NOT NULL, email VARCHAR2 (100), upoint NUMBER DEFAULT 0, regdate TIMESTAMP DEFAULT sysdate, updatedate TIMESTAMP DEFAULT sysdate )NOCACHE LOGGING;
더미 데이터 생성 반복문으로 생성
쿼리는 정확하다. mid 의 primary key 로 id 증가 가 필요하다.
declare -- 선언문 i number := 1; begin while i <=1000 loop -- 1000건 입력 INSERT INTO TBL_MEMBER ( mid, USERID, USERPW, USERNAME, EMAIL) VALUES( (select nvl(max(mid)+1,1) from tbl_member), concat('userid', (select nvl(max(mid)+1,1) from tbl_member)), 'userpw', 'username', 'email'); i := i+1; end loop; end ; commit;
방법
between A and B 쿼리 방식
* 페이지 나누기
- 페이지당 게시물수 : 10개
- 전체 게시물수 : 999개
- 몇 페이지? : 100
999 / 10 => 99.9 올림 => 100
- 페이지의 시작번호, 끝번호 계산
where rn between 1 and 10
1페이지 => 1 ~ 10
2페이지 => 11 ~ 20
....
11페이지 => 101 ~ 110
57페이지 => 561 ~ 561
99페이지 => 981 ~ 990
100페이지 => 991 ~ 1000
시작번호=(현재페이지 - 1 ) * 페이지당게시물수 + 1
1페이지 => (1-1) * 10 + 1 => 1
2페이지 => (2-1) * 10 + 1 => 11
7페이지 => (7-1) * 10 + 1 => 61
끝번호=시작번호 + 페이지당게시물수 - 1
1페이지 => 1 + 10 - 1 => 10
2페이지 => 11 + 10 - 1 => 20
* 전체 페이지 블록수
전체페이지갯수 / 10
57 / 10 => 5.7 => 6개
1 2 3 4 5 6 7 8 9 10 [다음]
[이전] 11 12 13 14 15 16 17 18 19 20 [다음]
[이전] 41 42 43 44 45 46 47 48 49 50 [다음]
[이전] 51 52 53 54 55 56 57 58 59 60 [다음]
[이전] 61 62
현재 페이지가 속한 블록
(현재페이지-1)/페이지블록단위 + 1
1페이지 => 몇번째 블록? 1
(1-1)/10 + 1 =>1
9페이지 => 1블록
(9-1)/10 + 1 => 1
11페이지 => 2블록
(11-1)/10 + 1 =>2
57페이지
(57-1)/10 + 1 =>6
* 페이지 블록의 시작번호
(현재블록-1)*블록단위+1
1블록 => (1-1)*10 + 1 => 1
2블록 => (2-1)*10 + 1 => 11
6블록 => (6-1)*10 + 1 => 51
* 페이지 블록의 끝번호
블록시작번호+블록단위-1;
1블록 => 1+10-1 => 10
2블록 => 11+10-1 => 20
6블록 => 51+10-1 => 60
★ 소스
OraclePageMakerAndSearch
package config.paging.oracle; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; //오라클 페이징 public class OraclePageMakerAndSearch { //페이지당 게시물 수 public int perPageNum ; //화면당 페이지 수 public static int BLOCK_SCALE =10; private Integer page=1; //현재 페이지 private int prevPage; //이전 페이지 private int nextPage; // 다음 페이지 private int totPage; // 전체 페이지 개수 private int totBlock; //전체 페이지 블록 개수 private int curBlock; //현재 페이지 블록 private int prevBlock; //이전 페이지 블록 private int nextBlock; //다음 페이지 블록 // where rn between #{start } and #{end} private int pageBegin; //#{start} private int pageEnd; // #{end} private int blockBegin;// 현재 페이지에 시작번호 [이전] private int blockEnd; // 현재 페이지에 끝 번호 [끝] private int totalCount; //전체 갯수 //검색처리 추가 private String searchType; private String keyword; //생성자 public OraclePageMakerAndSearch(){ this.page=1; //초기 페이지는 1 this.perPageNum=10; //10 개씩 보여준다. } public void setTotPage(int count) { this.totalCount=count; curBlock =1; //현재 페이지 블록 번호 //991/10 =99.1 올림 처리 // Math.ceil(실수) 올림 처리 this.totPage = (int)Math.ceil(count*1.0/perPageNum); //between #{start} and #{end} 에 입력될 값 계산 setPageRange(); setTotBlock(); //전체 페이지 블록 개수 계산 //페이지 블록의 시작, 끝 번호 계산 setBlockRange(); } private void setBlockRange() { //현재 페이지에 몇번째 페이지 블록에 속하는지 계산 curBlock=(int)Math.ceil((page-1)/BLOCK_SCALE)+1; //현재 페이지 블록의 시작, 끝 번호 계산 blockBegin =(curBlock -1) * BLOCK_SCALE +1; blockEnd=blockBegin+BLOCK_SCALE-1; //마지막 블록이 범위를 초과하지 않도록 처리 if(blockEnd > totPage) blockEnd=totPage; //[이전] 을 눌렸을 때 이동할 페이지 번호 prevPage=(curBlock==1)? 1:(curBlock-1)*BLOCK_SCALE; //[다음] 을 눌렸을 때 이동할 페이지 번호 nextPage=curBlock > totBlock ? (curBlock * BLOCK_SCALE) : (curBlock*BLOCK_SCALE)+1; if(nextPage >= totPage) nextPage = totPage; } private void setPageRange() { //where rn between #{start } and #{end} 에 입력 될 값 // 시작 번호 = (현재 페이지 -1 ) * 페이지당 게시물 수 +1; // ex (5-1) * 10 +1 = 41페이지 pageBegin=(page-1)* perPageNum+1; //끝번호 = 시작번호 + 페이지당 게시물 수 -1; pageEnd=pageBegin + perPageNum-1; } public Integer getPage() { return page; } public void setPage(Integer page) { //페이지 번호가 0이거나 0보다 작으면 1페이지로 한다. if(page <=0){ this.page=1; return; } this.page = page; } //페이지 블록의 갯수 계산 (총 100 페이지라면 10개 블록) public void setTotBlock() { this.totBlock = (int)Math.ceil(totPage/BLOCK_SCALE); } //일반적인 페이징 처리 파라미터 출력 데이터 ex) /memberList?page=4&perPageNum=10 public String makeQuery(int page){ UriComponents uriComponents= UriComponentsBuilder.newInstance() .queryParam("page", page) .queryParam("perPageNum", perPageNum) .build(); return uriComponents.toUriString(); } //일반적인 페이징 부트스트랩 출력 public String bootStrapPagingHTML(String url){ StringBuffer sBuffer=new StringBuffer(); sBuffer.append("<ul class='pagination'>"); if(curBlock >1){ sBuffer.append("<li><a href='"+url+makeQuery(1)+"'>처음</a></li>"); } if(curBlock >1){ sBuffer.append("<li><a href='"+url+makeQuery(prevPage)+"'>«</a></li>"); } String active=""; for(int i=blockBegin; i <=blockEnd; i++){ if(page==i){ active="class=active"; }else{ active=""; } sBuffer.append("<li " +active+" >"); sBuffer.append("<a href='"+url+makeQuery(i)+"'>"+i+"</a></li>"); sBuffer.append("</li>"); } if(curBlock < totBlock){ sBuffer.append("<li><a href='"+url+makeQuery(nextPage)+"'>»</a></li>"); } if(curBlock < totBlock){ sBuffer.append("<li><a href='"+url+makeQuery(totPage)+"'>마지막</a></li>"); } sBuffer.append("</ul>"); return sBuffer.toString(); } //검색 추가 페이지 파라미터 public String makeSearch(int page){ UriComponents uriComponents= UriComponentsBuilder.newInstance() .queryParam("page", page) .queryParam("perPageNum", perPageNum) .queryParam("searchType", searchType) .queryParam("keyword", keyword) .build(); return uriComponents.toUriString(); } //검색 추가 페이징 부트스트랩 출력 public String bootStrapPagingSearchHTML(String url){ StringBuffer sBuffer=new StringBuffer(); sBuffer.append("<ul class='pagination'>"); if(curBlock >1){ sBuffer.append("<li><a href='"+url+makeSearch(1)+"'>처음</a></li>"); } if(curBlock >1){ sBuffer.append("<li><a href='"+url+makeSearch(prevPage)+"'>«</a></li>"); } String active=""; for(int i=blockBegin; i <=blockEnd; i++){ if(page==i){ active="class=active"; }else{ active=""; } sBuffer.append("<li " +active+" >"); sBuffer.append("<a href='"+url+makeSearch(i)+"'>"+i+"</a></li>"); sBuffer.append("</li>"); } if(curBlock < totBlock){ sBuffer.append("<li><a href='"+url+makeSearch(nextPage)+"'>»</a></li>"); } if(curBlock < totBlock){ sBuffer.append("<li><a href='"+url+makeSearch(totPage)+"'>마지막</a></li>"); } sBuffer.append("</ul>"); return sBuffer.toString(); } public int getPrevPage() { return prevPage; } public void setPrevPage(int prevPage) { this.prevPage = prevPage; } public int getNextPage() { return nextPage; } public void setNextPage(int nextPage) { this.nextPage = nextPage; } public int getTotPage() { return totPage; } public int getTotBlock() { return totBlock; } public int getCurBlock() { return curBlock; } public void setCurBlock(int curBlock) { this.curBlock = curBlock; } public int getPrevBlock() { return prevBlock; } public void setPrevBlock(int prevBlock) { this.prevBlock = prevBlock; } public int getNextBlock() { return nextBlock; } public void setNextBlock(int nextBlock) { this.nextBlock = nextBlock; } public int getPageBegin() { return pageBegin; } public void setPageBegin(int pageBegin) { this.pageBegin = pageBegin; } public int getPageEnd() { return pageEnd; } public void setPageEnd(int pageEnd) { this.pageEnd = pageEnd; } public int getBlockBegin() { return blockBegin; } public void setBlockBegin(int blockBegin) { this.blockBegin = blockBegin; } public int getBlockEnd() { return blockEnd; } public void setBlockEnd(int blockEnd) { this.blockEnd = blockEnd; } public int getPerPageNum() { return perPageNum; } public void setPerPageNum(int perPageNum) { //몇개 씩 보여줄것인가 이다. 최대 100개씩 보여 줄것으로 설정한다. //만약 0보다 작거나 100 보다 크면 10으로 초기화 시킨다. if(perPageNum <=0 || perPageNum >100){ this.perPageNum=10; return; } this.perPageNum = perPageNum; } public String getSearchType() { return searchType; } public void setSearchType(String searchType) { this.searchType = searchType; } public String getKeyword() { return keyword; } public void setKeyword(String keyword) { this.keyword = keyword; } }
Controller
페이징 카운터 값만 넘겨주면 된다.
//페이징 and Search @RequestMapping(value="/oracleMemberListSearch", method=RequestMethod.GET) public String oracleListPageSearch(@ModelAttribute("pageMaker") OraclePageMakerAndSearch pageMaker, Model model) throws Exception{ //전체 페이지 개수 구한후 하단 페이징 처리 하기 pageMaker.setTotPage(service.oralcleLlistPageCount(pageMaker)); //페이지 메이커 attribute 로 저장 model.addAttribute("pageMaker", pageMaker); model.addAttribute("list", service.oralcleListPageSearch(pageMaker)); return "test/oracleMemberList"; }
View
페이징 처리만
<tr> <td colspan="8" class="text-center"> <ul class="pagination"> <!-- [처음] --> <c:if test="${pageMaker.curBlock >1 }"> <li><a href="oracleMemberListSearch?page=1&perPageNum=10" >[처음]</a></li> </c:if> <!-- [이전] --> <c:if test="${pageMaker.curBlock >1 }"> <li><a href="oracleMemberListSearch?page=${pageMaker.prevPage}&perPageNum=10" >[이전]</a></li> </c:if> <c:forEach var="num" begin="${pageMaker.blockBegin}" end="${pageMaker.blockEnd}"> <c:choose> <c:when test="${num == pageMaker.page}"> <li class='active'><a href="oracleMemberListSearch?page=${num}&perPageNum=10">${num}</a></li> </c:when> <c:otherwise> <li> <a href="oracleMemberListSearch?page=${num}&perPageNum=30">${num}</a></li> </c:otherwise> </c:choose> </c:forEach> <!-- [다음] --> <c:if test="${pageMaker.curBlock < pageMaker.totBlock }"> <li><a href="oracleMemberListSearch?page=${pageMaker.nextPage}&perPageNum=10" >[다음]</a></li> </c:if> <!-- [마지막] --> <c:if test="${pageMaker.curBlock < pageMaker.totBlock }"> <li><a href="oracleMemberListSearch?page=${pageMaker.totPage}&perPageNum=10" >[마지막]</a></li> </c:if> </ul> </td> </tr>
makeQuery() 사용
<tr> <td colspan="8" class="text-center"> <ul class="pagination"> <!-- [처음] --> <c:if test="${pageMaker.curBlock >1 }"> <li><a href="oracleMemberListSearch${pageMaker.makeQuery(1) }" >[처음]</a></li> </c:if> <!-- [이전] --> <c:if test="${pageMaker.curBlock >1 }"> <li><a href="oracleMemberListSearch${pageMaker.makeQuery(pageMaker.prevPage) }" >«</a></li> </c:if> <c:forEach var="num" begin="${pageMaker.blockBegin}" end="${pageMaker.blockEnd}"> <c:choose> <c:when test="${num == pageMaker.page}"> <li class='active'><a href="oracleMemberListSearch${pageMaker.makeQuery(num) }">${num}</a></li> </c:when> <c:otherwise> <li> <a href="oracleMemberListSearch${pageMaker.makeQuery(num) }">${num}</a></li> </c:otherwise> </c:choose> </c:forEach> <!-- [다음] --> <c:if test="${pageMaker.curBlock < pageMaker.totBlock }"> <li><a href="oracleMemberListSearch${pageMaker.makeQuery(pageMaker.nextPage) }" >»</a></li> </c:if> <!-- [마지막] --> <c:if test="${pageMaker.curBlock < pageMaker.totBlock }"> <li><a href="oracleMemberListSearch${pageMaker.makeQuery(pageMaker.totPage) }" >[마지막]</a></li> </c:if> </ul> </td> </tr>
페이징 부트스트랩 bootStrapPagingHTML 사용
<tr> <td colspan="8" class="text-center"> ${pageMaker.bootStrapPagingHTML('oracleMemberListSearch') } </td> </tr>
검색 추가 페이징 부트스트랩 bootStrapPagingSearchHTML 사용 - 이것을 사용하면 된다.
<tr> <td colspan="8" class="text-center"> ${pageMaker.bootStrapPagingSearchHTML('oracleMemberListSearch') } </td> </tr>
검색 폼 처리
<div class="row"> <div class="col-xs-3 col-sm-3"> </div> <div class="col-xs-8 col-sm-8"> <div class="text-right"> <div class="box-body"> <div class="col-sm-4"> <select name="searchType" class="form-control" id="searchType"> <option value="n" <c:out value="${pageMaker.searchType == null ? 'selected' : '' }"/> >----</option> <option value="userid" <c:out value="${pageMaker.searchType eq 'userid' ? 'selected' : '' }"/> >아이디</option> <option value="username" <c:out value="${pageMaker.searchType eq 'username' ? 'selected' : '' }"/> >이름</option> <option value="email" <c:out value="${pageMaker.searchType eq 'email' ? 'selected' : '' }"/> >이메일</option> <option value="all" <c:out value="${pageMaker.searchType eq 'all' ? 'selected' : '' }"/> >아이디 or 이름 or 이메일</option> </select> </div> <div class="col-sm-4"> <input type="text" name="keyword" id="keywordInput" class="form-control" value="${pageMaker.keyword}"> </div> <div class="col-sm-4 text-left"> <button id="searchBtn" class="btn btn-success" >검색</button> </div> </div> </div> </div> </div>
자바스크립트 처리
makeQuery 을 사용해라 makeSearch() 사용시 검색 파라미터 중복 현상이 나타나 에러가 발생한다.
<script> $(document).ready(function(){ $("#searchBtn").on("click", function(event){ var url ="oracleMemberListSearch${pageMaker.makeQuery(1)}"; url +="&searchType="+searchType()+"&keyword="+keywordInput(); self.location =url; }); }); function searchType(){ return $("#searchType").val(); } function keywordInput(){ return $("#keywordInput").val(); } </script>
★ 최신등록순으로 내림차순 정렬을 하고 싶을 때 쿼리 만드는 방법
1) rownum 없이 등록일 또는 index 로 내림차순 정렬을 한다. (첫번째 정렬은 rownum 없이 정렬해야 한다.)
2)FROM 절에서 묶어 주고 셀렉트 절에서 rownum 으로 번호를 매긴다.
3) 다시한번 FROM 절로 묶은 다음에 rownum 을 where rn BETWEEN #{pageBegin} and #{pageEnd} 한다.
4) 아래 결과 이미지 처럼 rn 1번 부터 순서대로 출력되는 것을 볼수 있는데, 이것을 jsp 화면 단에서 전체 카운트에서 빼는 방법으로 처리 하면된다.
<c:forEach var="row" items="${list}" > ${pageMaker.totalCount-row.rn+1} </c:forEach>
Mapper
<sql id="search"> <if test="searchType !=null"> <if test="searchType == 'userid'.toString()"> and userid like '%' || #{keyword} || '%' </if> <if test="searchType == 'username'.toString()"> and username like '%' || #{keyword} || '%' </if> <if test="searchType == 'email'.toString()"> and email like '%' || #{keyword} || '%' </if> <if test="searchType == 'all'.toString()"> and ( userid like '%' || #{keyword} || '%' OR username like '%' || #{keyword} || '%' OR email like '%' || #{keyword} || '%' ) </if> </if> </sql> <!-- 회원 목록 출력 페이징 처리 및 검색처리 --> <select id="listPageSearch" resultType="net.macaronics.web.domain.MemberVO"> <![CDATA[ SELECT * FROM ( SELECT rownum as rn , RE.* FROM ( SELECT * FROM tbl_member WHERE mid >0 ]]> <include refid="search" /> <![CDATA[ ORDER BY mid DESC ) RE ) WHERE rn BETWEEN #{pageBegin} and #{pageEnd} ]]> </select> <select id="listPageCount" resultType="int"> <![CDATA[ select count(mid) from TBL_MEMBER where mid >0 ]]> <include refid="search" /> </select>
select * from ( select rownum as rn , A.* from ( select * from tbl_member order by mid desc ) A ) where rn >=1 and rn <=10
유사 방법 참조
Jsp 스프링, 게시판 페이징 처리 부트스트랩 소스 클래스 - 88 - 15 - ★★★
댓글 ( 6)
댓글 남기기