[JAVA] JDK 실습 (5)
들어가기 전에...
- guest316배포(email).txt 파일 다운로드
- 복사/붙여넣기 해서 모든 테이블 생성/데이터 저장하기
페이징 기능 구현
[1] [2] ~ [7클릭] [9] [10] [다음]
위와 같은 페이징에서 7을 클릭했을 때, guest 테이블에서 61~70행 데이터 출력하는 것.
아래 select문을 떠올린 다음 이를 활용해서 코드를 작성해보자!
select * from (select rownum rn, g.* from guest g) where rn between 61 and 70;
guestList.jsp (testList.jsp > Save as... > guestList.jsp)
<body>
<p>
<%
msg ="select count(*) as cnt from guest " ;
ST = CN.createStatement();
RS = ST.executeQuery(msg);
if(RS.next()==true){ total = RS.getInt("cnt"); }
%>
- "select count(*) as cnt from guest " - 위에서 작성한 쿼리문을 용도에 맞게 잘 다듬어 정리한다.
- createStatement() - 데이터베이스로 SQL 문을 보내기 위한 SQLServerStatement 개체를 만든다.
- ST.executeQuery(queryMsg) - SELECT 구문을 수행할 때 사용되는 함수다. 수행결과로 ResultSet 객체의 값을 반환한다.
- getInt(java.lang.String columnName) - 현재 행에서 지정된 열 이름의 값을 Java 프로그래밍 언어의 int로 검색한다.열 이름이 포함된 문자열을 인자로 받는다.
- getInt(1)에서 숫자는 '1'은 select문에서 첫 번째 항목(oseq)을 가져오라는 의미다.
여기서부터 페이징 작업을 시작한다.
<%
int rowstart=0, rowend=0 ;
String pnum="" ;
int pageNUM=1 ; // 현재 페이지 숫자
int pagecount=0; // 페이지 개수 ex)32
int tmp=0, startpage=1, endpage=10 ;
pnum = request.getParameter("pageNum"); //처음실행하면 넘어오는 pageNum값이 없어서 에러발생
if(pnum==null || pnum=="" || pnum.equals("")){ pnum="1";} // 에러를 막기 위한 초기화
pageNUM = Integer.parseInt(pnum); // 숫자로 변환
rowstart = (pageNUM-1)*10+1 ;
rowend = pageNUM * 10 ;
[1][2][3][4][5][6][7][8][9][10] [다음] 의 형태로 만들기 위해 startpage = 1, endpage = 10 으로 지정한다.
초기 현재 페이지는 1페이지며,
한 페이지 당 보여지는 데이터 개수는 10개다.
(여기에 대한 수식이 rowstart, rowend에 적용되어 있다.)
Ex. 1페이지의 경우 데이터 (1-1)*10+1 = 1 부터 1*10 = 10 까지 출력
5페이지의 경우 데이터 (5-1)*10+1 = 41 부터 1*10 = 50 까지 출력
if(total%10==0){ pagecount=(total/10); }
else{ pagecount=(total/10)+1; }
위에서 설명한 대로 한 페이지 당 보여지는 데이터 개수 10개로 했을 때
데이터 개수가 10으로 나눠 떨어지면 그대로 pagecount가 되고,
나누어 떨어지지 않으면 나머지 데이터 개수까지 보여줄 페이지 +1개가 필요하다.
Ex. 총 데이터 개수가 63개라면 10개씩 보여주는 페이지 6개와 나머지 3개를 보여줄 페이지 +1개가 필요하다.
tmp = (pageNUM-1)%10; // 6
startpage = (pageNUM-tmp) ; // 17-6=11
endpage = (startpage+9); // 20
//[이전] [31startpage] ~ [32]~[40][다음X]
if(endpage>pagecount){ endpage=pagecount; }
%>
클릭 페이지가 달라질 때마다 startpage와 endpage 를 계산하여 갱신한다.
Ex. [11] ~ [pageNUM=17클릭] ~ [20] [다음] 라고 가정했을 때,
rowstart=161 rowend=170
startpage=11 endpage=20
만약 endpage 가 총 페이지 개수보다 크면(= 총 페이지가 끝나면) endpage = pagecount 로 할당한다.
보여지는 html 문서는 아래와 같다.
<p>
<h2>guestList페이징.jsp</h2>
<table border="1" width="1000" cellspacing="0">
<tr align="right">
<td colspan="6">
<a href="index.jsp">[index]</a>
<a href="guestList.jsp">[guestList]</a>
데이터개수 : <%= total %>
</td>
</tr>
<tr bgcolor="yellow" height="50">
<td>행번호</td> <td>사 번</td> <td>이 름</td> <td>제 목</td> <td>메 일</td> <td>급 여</td>
</tr>
테이블에 데이터를 출력하는 부분이다.
<%
String a= "select * from ( ";
String b= "select rownum rn, g.* from guest g";
String y= "";
String c= " ) where rn between " + rowstart + " and " + rowend ;
msg=a+b+c;
System.out.println( c );
ST = CN.createStatement();
RS = ST.executeQuery(msg);
while(RS.next()==true){
%>
쿼리문을 조건에 따라 4구역으로 나눈 뒤 변수를 대입하고, 이를 전체적으로 연결하여 쿼리문을 보낸다.
만약 다음 데이터가 존재하면 아래와 같이 데이터 행을 출력한다.
<tr>
<td> <%= RS.getInt("rn") %> </td>
<td> <%= RS.getInt("sabun") %> </td>
<td> <%= RS.getString("name") %> </td>
<td> <%= RS.getString("title") %> </td>
<td> <%= RS.getString("email") %> </td>
<td> <%= RS.getInt("pay") %> </td>
</tr>
<% } // while end
페이징 부분 html 형태는 다음과 같이 출력한다.
<tr align="center">
<td colspan="6">
<%
if(startpage>10){
out.println("<a href=guestList.jsp?pageNum="+(startpage-10)+">[이전]</a>");
}
for(int i=startpage; i<=endpage; i++){
if(i==pageNUM){
out.println("<font style='font-size:24pt; color:blue'>["+i+"]</font>");
}else{
out.println("<a href=guestList.jsp?pageNum="+i+">["+i+"]</a>");
}
}
//다음 endpage 1~10 11~20 21~30 31~40 총페이지수pagecount=32
//endpage ~10, ~20, ~30, ~40
if(endpage<pagecount){
out.println("<a href=guestList.jsp?pageNum="+(startpage+10)+">[다음]</a>");
}
%>
</td>
</tr>
[이전X]1~10[다음] [이전]11~20[다음] [이전]21~30[다음] [이전]31~ 총페이지수pagecount=32
와 같이 그려져야 한다.
그러기 위해서 startpage는 1~, 11~, 21~, 31~ 의 형태를 가진다.
이를 if제어문으로 구현하면
- startpage가 10 이상이면 [이전]버튼을 생성한다.
- startpage부터 endpage까지 순회하는데, 클릭한 페이지의 글자는 파란색으로 강조한다.
- endpage가 마지막 페이지보다 작으면 [다음] 버튼을 생성한다.
검색 기능 구현
- 검색을 하면...
- http://localhose:8181/Web0812/guestList.jsp?pageNum=3&keyfield=name&keyword=b
- 이런 식으로 url을 전송하게 만들 것이다.
- 검색에 사용 할 SQL문은 아래와 같다.
// name에 b가 들어간 데이터 select 하기
select * from guest where name like '%b%' ;
// name에 b가 들어간 데이터 개수
select count(*) as scnt from guest where name like '%b' ;
// 전체 출력
select * from guest where title like '%%' ;
// 검색어 입력
select * from guest where title like '%p%' ;
// 검색어 입력 + 행번호
select * from(select rownum rn g* from where name like '%b%') g where rn between 51 and 60
guestList.jsp
위 페이징 코드와 동일한 부분은 생략하고 오로지 검색 기능에 대한 부분만 설명한다.
검색에 사용되는 전역 변수는 다음과 같다.
<body>
<%
String sqry;
String skey, sval;
String returnpage;
- sqry - 검색에 사용 될 쿼리문을 담을 변수
- skey - 컬럼 필드(=검색대상) 종류
- sval - 검색어를 담을 변수
- returnpage - 검색 대상/검색어
skey = request.getParameter("keyfield"); // 검색대상 = 컬럼필드
sval = request.getParameter("keyword"); // 검색어
returnpage="&keyfield="+skey+"&keyword="+sval;
두 input란에서 검색 대상과 검색어를 가져온다.
// 검색어 입력을 안 받았을 때 전체 출력
if(skey=="" || sval=="" || skey==null || sval==null || skey.equals("")){
skey = ""; sval = "";
sqry = " where title like '%%' " ;
}else{ sqry=" where " + skey + " like '%"+ sval +"%'" ; }
Smsg = "select count(*) as scnt from guest " + sqry;
ST = CN.createStatement();
RS = ST.executeQuery(Smsg);
if(RS.next()==true){ Stotal = RS.getInt("scnt"); }
System.out.println("검색데이터건수 = "+ Stotal);
%>
검색 대상, 검색어를 입력받지 않았을 땐 전체 출력을 한다. 검색 대상 및 검색어를 입력받은 경우 where, like 조건문을 써 쿼리문을 작성한다.
- Stotal - 총 검색 데이터 건수
데이터를 출력하는 테이블 상단에 조회건수/전체건수 를 표시를 추가한다.
<p>
<h2>guestList검색.jsp</h2>
<table border="1" width="1000" cellspacing="0">
<tr align="right">
<td colspan="6">
<a href="index.jsp">[index]</a>
<a href="guestList.jsp">[guestList]</a>
<%= Stotal %>조회건/<%= total %>전체건
</td>
</tr>
페이징 쿼리문 + 검색 쿼리문을 합친 결과다.
<%
String a= "select * from ( ";
String b= " select rownum rn, g.* from ";
String y= "( select * from guest " + sqry + ") g ";
String c= ") where rn between " + rowstart + " and " + rowend ;
msg=a+b+y+c;
ST = CN.createStatement();
RS = ST.executeQuery(msg);
%>
a+b+c 였던 페이징 쿼리문에서 검색 쿼리문인 y가 추가되었다.
검색 대상 및 검색어를 입력 받는 html 형태는 아래와 같다.
<tr align="center">
<td colspan="6">
<form action="guestList.jsp">
<select name="keyfield" onchange="">
<option value="">---검색대상선택---</option>
<option value="name">이름검색</option>
<option value="title">제목검색</option>
<option value="">내용검색</option>
<input type=text name="keyword" size=8 value="">
<input type="submit" value="검색">
</select>
</form>
</td>
</tr>
</table>
</body>
댓글 수 표시 기능 구현
댓글 테이블을 생성하고 댓글 데이터를 삽입한다.
일단 같은 이름의 테이블을 전에 만들었을 수도 있으니까 없애주고
drop sequence guestreply_seq ;
drop table guestreply;
commit ;
댓글 테이블을 생성한다.
create sequence guestreply_seq
start with 1 ;
increment by 1 ;
select sequence_name from user_sequences ;
create table guestreply ( --댓글관련 테이블 guestreply
num number(4) not null, --시퀀스 guestreply_seq.nextVal
writer varchar2(10) not null,
content varchar2(20)not null,
sabun number(4) not null --guest테이블의 sabun필드와 연결
);
commit ;
시퀀스를 생성하고
drop sequence guestreply_seq ;
create sequence guestreply_seq ;
commit ;
외래키를 설정한다.
alter table guestreply drop constraint guest_sabun_fk;
alter table guestreply add constraint guest_sabun_fk
foreign key(sabun) references guest(sabun) on delete cascade;
commit ;
데이터를 저장한다.
insert into guestreply values(guestreply_seq.nextval, 'aaa','bbb',4466 );
insert into guestreply values(guestreply_seq.nextval, 'kim','kim',4466);
insert into guestreply values(guestreply_seq.nextval, 'lee','lee', 4477);
insert into guestreply values(guestreply_seq.nextval, 'lee','lee',4466);
commit;
guestList.jsp - 댓글 수 표시
<body>
<%
String a="select * from ( ";
String b=" select rownum rn, g.*, (select count(*) from guestreply r where r.sabun=g.sabun) as rcnt from ";
String y="( select * from guest " + sqry + ") g ";
String c=") where rn between " + rowstart + " and " + rowend ;
msg=a+b+y+c;
System.out.println( y );
ST = CN.createStatement();
RS = ST.executeQuery(msg);
while(RS.next()==true){
Rcnt = RS.getInt("rcnt");
Gtitle = RS.getString("title");
Gemail = RS.getString("email");
Gpay = RS.getInt("pay") ;
%>
b 부분에 댓글 수를 가져오는 쿼리문이 추가되었다.
<tr>
<td> <%= RS.getInt("rn") %> </td>
<td> <%= RS.getInt("sabun") %> </td>
<td> <%= RS.getString("name") %> </td>
<td> <%= Gtitle %><%if(Rcnt>0){%>
<span style="color:red;font-weight:bold";>[<%=Rcnt %>]</span><%}%>
</td>
<td> <%= RS.getString("email") %> </td>
<td> <%= Gpay %> </td>
</tr>
<% }//while end %>
</body>
댓글 수 Rcnt가 0 이라면 bold체로 제목 옆에 출력한다.