한페이지당 글이 5개씩 들어가도록 페이징
-rownum 줄번호 활용
select bbsno,wname, readcnt, indent, regdt
from tb_bbs
order by grpno desc, ansnum asc;
2.
select bbsno,wname, readcnt, indent, regdt,rownum
from tb_bbs
order by grpno desc, ansnum asc;
3. 셀프조인 후,rownum
select bbsno,wname, readcnt, indent, regdt,rownum
from(
select bbsno,wname, readcnt, indent, regdt
from tb_bbs
order by grpno desc, ansnum asc);
----글 5개를 기준으로 자름
4.
---1~5
select bbsno,wname, readcnt, indent, regdt,rownum
from(
select bbsno,wname, readcnt, indent, regdt
from tb_bbs
order by grpno desc, ansnum asc)
where rownum<=5;
5.--6~10행 출력하기
-- 선택된 레코드가 없음
select bbsno,wname, readcnt, indent, regdt,rownum
from(
select bbsno,wname, readcnt, indent, regdt
from tb_bbs
order by grpno desc, ansnum asc)
where rownum>=6 and rownum<=10;
6.--6~10행 출력하기
--한번 더 검색해서 join
select *
from(
select bbsno,wname, readcnt, indent, regdt,rownum as r
from(
select bbsno,wname, readcnt, indent, regdt
from tb_bbs
order by grpno desc, ansnum asc))
where r>=6 and r<=10;
7.
--페이징 + 검색
파스타가 있는 행을 검색해서 2페이지 조회하시오
select *
from(
select bbsno,wname, readcnt, indent, regdt,rownum as r
from(
select bbsno,wname, readcnt, indent, regdt
from tb_bbs
where subject like '%파스타%'
order by grpno desc, ansnum asc))
where r>=6 and r<=10;
int nowPage=1;
if(request.getParameter("nowPage")!=null){
nowPage=Integer.parseInt(request.getParameter("nowPage"));
}
%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="ssi.jsp" %>
<%@ include file="../header.jsp" %>
<!-- 본문 시작 -->
<h3>글목록</h3>
<p><a href="bbsForm.jsp">글쓰러 가기</a></p>
<table class="table table-hover" border="1">
<thead>
<tr class="info" >
<th>제목</th>
<th>조회수</th>
<th>작성자</th>
<th>등록일</th>
</tr>
</thead>
<tbody>
<%
//한페이지당 출력할 행의 갯수
//페이지 요청이 없는 경우 1페이지가 무조건 출력
int recordPerPage=5;
ArrayList<BbsDTO> list = dao.list3(col,word,nowPage,recordPerPage);
if(list==null){
out.println(" <tr>");
out.println(" <td colspan='5'>" );
out.println(" <strong> 작성 글없음 <strong>" );
out.println(" </td>" );
out.println(" <tr>");
}else{
//오늘 날짜를 문자열로 2023-04-14
String today=Utility.getDate();
for(int i=0;i<list.size();i++){
dto=list.get(i);
%>
<tr>
<td style="text-align:left">
<%
//답변 이미지 출력
for(int n=1;n<=dto.getIndent();n++){
out.println("<img src='../images/reply.gif'>");
}
%>
<a href="bbsRead.jsp?bbsno=<%=dto.getBbsno()%>&col=<%=col%>&word=<%=word%>&nowPage=<%=nowPage%>"><%=dto.getSubject()%></a>
<%
//오늘 작성한 글 제목 뒤에 new 이미지 출력
//작성일(regdt)에서 년월일 자르기
String regdt=dto.getRegdt().substring(0,10);
if(regdt.equals(today)){
out.println("<img src='../images/new.gif'>");
}
//조회수 10이상 hot 이미지 출력
if(dto.getReadcnt()>=10){
out.println("<img src='../images/hot.gif'>");
}
%>
</td>
<td><%=dto.getReadcnt() %></td>
<td><%=dto.getWname() %></td>
<td><%=dto.getRegdt().substring(0,10) %>
</td>
</tr>
<%
}
int totalRecord=dao.count2(col,word);
out.println("<tr>");
out.println("<td colspan='4' style='text-align:center;'>");
out.println(" 글갯수:<strong>" +totalRecord +"</strong>");
out.println("</td>");
out.println("</tr>");
//페이지 리스트
out.println("<tr>");
out.println("<td colspan='4' style='text-align:center; height:50px'>");
//String paging=new Paging().paging1(totalRecord, nowPage, recordPerPage, col, word, "bbsList.jsp") ;
String paging=new Paging().paging2(totalRecord, nowPage, recordPerPage, col, word, "bbsList.jsp") ;
out.println(paging);
out.println("</td>");
out.println("</tr>");
%>
<tr>
<td colspan="4" style='text-align: center; height: 50px'>
<form action="bbsList.jsp" onsubmit="return searchCheck()">
<select name="col">
<option value="subject_content">제목+내용
<option value="subject">제목
<option value="content">내용
<option value="wname">작성자
</select>
<input type="text" name="word" id="word">
<input type="submit" value="검색">
</form>
</td>
</tr>
<%
}
%>
</tbody>
</table>
<!-- 본문 끝 -->
<%@ include file="../footer.jsp" %>
위에서 정의한 sql문을 바탕으로 작성
public ArrayList<BbsDTO> list3(String col, String word,int nowPage, int recordPerPage) {
ArrayList<BbsDTO> list= null;
//페이지당 출력할 행의 갯수(10개를 기준)
//1 페이지 : WHERE r>=1 AND r<=10;
//2 페이지 : WHERE r>=11 AND r<=20;
//3 페이지 : WHERE r>=21 AND r<=30;
int startRow = ((nowPage-1) * recordPerPage) + 1 ;
int endRow = nowPage * recordPerPage;
try {
con=dbopen.getConnection();
sql=new StringBuilder();
word=word.trim();
if(word.length()==0) {//검색어가 존재하지 않는 경우
sql.append(" select * ");
sql.append(" from( ");
sql.append(" select bbsno, wname, readcnt,subject, indent, regdt,rownum as r ");
sql.append(" from( ");
sql.append(" select bbsno,wname, readcnt,subject, indent, regdt ");
sql.append(" from tb_bbs ");
sql.append(" order by grpno desc, ansnum asc)) ");
sql.append(" where r>=" + startRow +"and r<=" + endRow );
} else { //검색어가 존재하는 경우
sql.append(" select * ");
sql.append(" from( ");
sql.append(" select bbsno,wname, readcnt,indent,subject,regdt,rownum as r ");
sql.append(" from( ");
sql.append(" select bbsno,wname, readcnt,subject,indent, regdt ");
sql.append(" from tb_bbs ");
String search="";
if(col.equals("subject_content")) {
search+= " where subject like '%" +word+"%' ";
search+= " or content like '%" +word+"%' ";
}else if(col.equals("subject")) {
search+= " where subject like '%" +word+"%' ";
}else if(col.equals("content")) {
search+= " where content like '%" +word+"%' ";
}else if(col.equals("wname")) {
search+= " where wname like '%" +word+"%' ";
}
sql.append(search);
sql.append(" order by grpno desc, ansnum asc)) ");
sql.append(" where r>=" + startRow +"and r<=" + endRow );
}//if end
pstmt=con.prepareStatement(sql.toString());
rs=pstmt.executeQuery();
if(rs.next()){
list=new ArrayList<>();
do { //커서가 가리키는 한줄씩 저장
BbsDTO dto=new BbsDTO();
dto.setBbsno(rs.getInt("bbsno"));;
dto.setWname(rs.getString("wname"));
dto.setSubject(rs.getString("subject"));
dto.setReadcnt(rs.getInt("readcnt"));
dto.setRegdt(rs.getString("regdt"));
dto.setIndent(rs.getInt("indent"));
list.add(dto);//list에 저장
}while(rs.next());
}//if end
}catch (Exception e) {
System.out.println("목록 가져오기 실패"+e);
}finally {
DBClose.close(con,pstmt,rs);
}
return list;
}
페이징 관련 함수를 정의해서 사용한다.
package net.utility;
public class Paging {
/**
* 숫자 형태의 페이징, 1 페이지부터 시작
* 현재 페이지: 11 / 22 [이전] 11 12 13 14 15 16 17 18 19 20 [다음]
*
* @param totalRecord 전체 레코드수
* @param nowPage 현재 페이지
* @param recordPerPage 페이지당 레코드 수
* @return
*/
public String paging1(int totalRecord, int nowPage, int recordPerPage, String col, String word, String filenm){
int pagePerBlock = 10; // 블럭당 페이지 수
int totalPage = (int)(Math.ceil((double)totalRecord/recordPerPage)); // 전체 페이지
int totalGrp = (int)(Math.ceil((double)totalPage/pagePerBlock));// 전체 그룹
int nowGrp = (int)(Math.ceil((double)nowPage/pagePerBlock)); // 현재 그룹
int startPage = ((nowGrp - 1) * pagePerBlock) + 1; // 특정 그룹의 페이지 목록 시작
int endPage = (nowGrp * pagePerBlock); // 특정 그룹의 페이지 목록 종료
StringBuffer str = new StringBuffer();
str.append("<style>");
str.append(" #paging {text-align: center; margin-top: 5px; font-size: 1em;}");
str.append(" #paging A:link {text-decoration:none; color:black; font-size: 1em;}");
str.append(" #paging A:hover{text-decoration:underline; background-color: #ffffff; color:black; font-size: 1em;}");
str.append(" #paging A:visited {text-decoration:none;color:black; font-size: 1em;}");
str.append("</style>");
str.append("<DIV id='paging'>");
//str.append("현재 페이지: " + nowPage + " / " + totalPage + " ");
int _nowPage = (nowGrp-1) * pagePerBlock; // 10개 이전 페이지로 이동
if (nowGrp >= 2){
str.append("[<A href='./"+filenm+"?col="+col+"&word="+word+"&nowPage="+_nowPage+"'>이전</A>]");
}//if end
for(int i=startPage; i<=endPage; i++){
if (i > totalPage){
break;
}//if end
if (nowPage == i){ // 현재 페이지이면 강조 효과
str.append("<span style='font-size: 1.2em; font-weight: bold;'>"+i+"</span> ");
}else{
str.append("<A href='./"+filenm+"?col="+col+"&word="+word+"&nowPage="+i+"'>"+i+"</A> ");
}//if end
}//for end
_nowPage = (nowGrp * pagePerBlock)+1; // 10개 다음 페이지로 이동
if (nowGrp < totalGrp){
str.append("[<A href='./"+filenm+"?col="+col+"&word="+word+"&nowPage="+_nowPage+"'>다음</A>]");
}//if end
str.append("</DIV>");
return str.toString();
}
/**
* SPAN태그를 이용한 박스 모델의 지원, 1 페이지부터 시작
* 현재 페이지: 11 / 22 [이전] 11 12 13 14 15 16 17 18 19 20 [다음]
*
* @param totalRecord 전체 레코드수
* @param nowPage 현재 페이지
* @param recordPerPage 페이지당 레코드 수
* @return
*/
public String paging2(int totalRecord, int nowPage, int recordPerPage, String col, String word, String filenm){
int pagePerBlock = 10; // 블럭당 페이지 수
int totalPage = (int)(Math.ceil((double)totalRecord/recordPerPage)); // 전체 페이지
int totalGrp = (int)(Math.ceil((double)totalPage/pagePerBlock));// 전체 그룹
int nowGrp = (int)(Math.ceil((double)nowPage/pagePerBlock)); // 현재 그룹
int startPage = ((nowGrp - 1) * pagePerBlock) + 1; // 특정 그룹의 페이지 목록 시작
int endPage = (nowGrp * pagePerBlock); // 특정 그룹의 페이지 목록 종료
StringBuffer str = new StringBuffer();
str.append("<style>");
str.append(" #paging {text-align: center; margin-top: 5px; font-size: 1em;}");
str.append(" #paging A:link {text-decoration:none; color:black; font-size: 1em;}");
str.append(" #paging A:hover{text-decoration:none; background-color: #CCCCCC; color:black; font-size: 1em;}");
str.append(" #paging A:visited {text-decoration:none;color:black; font-size: 1em;}");
str.append(" .span_box_1{");
str.append(" font-size: 1em;");
str.append(" border: 1px;");
str.append(" border-style: solid;");
str.append(" border-color: #cccccc;");
str.append(" padding:0px 0px 0px 0px; /*위, 오른쪽, 아래, 왼쪽*/");
str.append(" margin:0px 0px 0px 0px; /*위, 오른쪽, 아래, 왼쪽*/");
str.append(" }");
str.append(" .span_box_2{");
str.append(" background-color: #CCCCCC;");
str.append(" font-size: 1em;");
str.append(" border: 1px;");
str.append(" border-style: solid;");
str.append(" border-color: #cccccc;");
str.append(" padding:0px 0px 0px 0px; /*위, 오른쪽, 아래, 왼쪽*/");
str.append(" margin:0px 0px 0px 0px; /*위, 오른쪽, 아래, 왼쪽*/");
str.append(" }");
str.append("</style>");
str.append("<DIV id='paging'>");
//str.append("현재 페이지: " + nowPage + " / " + totalPage + " ");
int _nowPage = (nowGrp-1) * pagePerBlock; // 10개 이전 페이지로 이동
if (nowGrp >= 2){
str.append("<A href='./"+filenm+"?col="+col+"&word="+word+"&nowPage="+_nowPage+"'><span class='span_box_1'>이전</span></A> ");
}
for(int i=startPage; i<=endPage; i++){
if (i > totalPage){
break;
}
if (nowPage == i){
str.append("<span class='span_box_2'> "+i+" </span> ");
}else{
str.append("<A href='./"+filenm+"?col="+col+"&word="+word+"&nowPage="+i+"'><span class='span_box_1'> "+i+" </span></A> ");
// 검색어+현재 페이지 가져감 filenm ->bbsList.jsp를 String filenm에 넘김
}
}
_nowPage = (nowGrp * pagePerBlock)+1; // 10개 다음 페이지로 이동
if (nowGrp < totalGrp){
str.append("<A href='./"+filenm+"?col="+col+"&word="+word+"&nowPage="+_nowPage+"'><span class='span_box_1'>다음</span></A> ");
}
str.append("</DIV>");
return str.toString();
}
/**
* SPAN태그를 이용한 박스 모델의 지원, 1 페이지부터 시작
* 현재 페이지: 11 / 22 [이전] 11 12 13 14 15 16 17 18 19 20 [다음]
*
* @param totalRecord 전체 레코드수
* @param nowPage 현재 페이지
* @param recordPerPage 페이지당 레코드 수
* @return
*/
public String paging3(int totalRecord, int nowPage, int recordPerPage, String col, String word, String filenm){
int pagePerBlock = 10; // 블럭당 페이지 수
int totalPage = (int)(Math.ceil((double)totalRecord/recordPerPage)); // 전체 페이지
int totalGrp = (int)(Math.ceil((double)totalPage/pagePerBlock));// 전체 그룹
int nowGrp = (int)(Math.ceil((double)nowPage/pagePerBlock)); // 현재 그룹
int startPage = ((nowGrp - 1) * pagePerBlock) + 1; // 특정 그룹의 페이지 목록 시작
int endPage = (nowGrp * pagePerBlock); // 특정 그룹의 페이지 목록 종료
StringBuffer str = new StringBuffer();
str.append("<style>");
str.append(" #paging {text-align: center; margin-top: 5px; font-size: 1em;}");
str.append(" #paging A:link {text-decoration:none; color:black; font-size: 1em;}");
str.append(" #paging A:hover{text-decoration:none; background-color: #CCCCCC; color:black; font-size: 1em;}");
str.append(" #paging A:visited {text-decoration:none;color:black; font-size: 1em;}");
str.append(" .span_box_1{");
str.append(" font-size: 1em;");
str.append(" border: 1px;");
str.append(" border-style: solid;");
str.append(" border-color: #cccccc;");
str.append(" padding:0px 0px 0px 0px; /*위, 오른쪽, 아래, 왼쪽*/");
str.append(" margin:0px 0px 0px 0px; /*위, 오른쪽, 아래, 왼쪽*/");
str.append(" }");
str.append(" .span_box_2{");
str.append(" background-color: #668db4;");
str.append(" color: #FFFFFF;");
str.append(" font-size: 1em;");
str.append(" border: 1px;");
str.append(" border-style: solid;");
str.append(" border-color: #cccccc;");
str.append(" padding:0px 0px 0px 0px; /*위, 오른쪽, 아래, 왼쪽*/");
str.append(" margin:0px 0px 0px 0px; /*위, 오른쪽, 아래, 왼쪽*/");
str.append(" }");
str.append("</style>");
str.append("<DIV id='paging'>");
//str.append("현재 페이지: " + nowPage + " / " + totalPage + " ");
int _nowPage = (nowGrp-1) * pagePerBlock; // 10개 이전 페이지로 이동
if (nowGrp >= 2){
str.append("<A href='./"+filenm+"?col="+col+"&word="+word+"&nowPage="+_nowPage+"'><span class='span_box_1'>이전</span></A> ");
}
for(int i=startPage; i<=endPage; i++){
if (i > totalPage){
break;
}
if (nowPage == i){
str.append("<span class='span_box_2'> "+i+" </span> ");
}else{
str.append("<A href='./"+filenm+"?col="+col+"&word="+word+"&nowPage="+i+"'><span class='span_box_1'> "+i+" </span></A> ");
}
}
_nowPage = (nowGrp * pagePerBlock)+1; // 10개 다음 페이지로 이동
if (nowGrp < totalGrp){
str.append("<A href='./"+filenm+"?col="+col+"&word="+word+"&nowPage="+_nowPage+"'><span class='span_box_1'>다음</span></A> ");
}
str.append("</DIV>");
return str.toString();
}
}//class end