1.페이지 분할이란?
웹페이지의 목록을 보여주는 list.jsp 파일을 만들었는데 그 목록이 너무 많이 있을때가 있습니다. 한페이지에 수백개의 리스트를 나열한다면 보기가 좋지 않습니다. 이것을 10개씩 보여준다고 하더라도 목록 갯수가 몇백개가 될수도 있습니다. 이렇기 때문에 페이지 분할 기능은 꼭 필요하다고 할수 있습니다. 또한 이미 웬만한 게시판을 보면 다음과 같이 페이지 분할이 되어있는것을 알수 있습니다.
하지만 이러한 목록을 실제로 구현하기 위해서는 조금 복잡한 쿼리문을 날려주어야 합니다. 먼저 한 페이지에 10개의 목록을 구하는 예제의 쿼리문은 다음과 같습니다.
SELECT boardno,title,wdate FROM (
SELECT ROWNUM R, A.* FROM (select boardno, title, wdate
FROM board ORDER BY boardno DESC) A)
WHERE R BETWEEN 1 and 10;
board라는 테이블에서 boardno, title, wdate라는 컬럼을 구하는 쿼리문 입니다. 가장 흔한 게시판에서 볼수 있는 형태로 여기서는 테이블 상위의 10개의 목록만을 구하는 쿼리문입니다. 1을 startNumber로 10을 endNumber로 선언해주고, 테이블명, 원하는 컬럼명을 바꾸면 자신이 원하는 목록을 구할수 있습니다.
SELECT 원하는컬럼1, 원하는컬럼2, 원하는컬럼3 FROM (
SELECT ROWNUM R, A.* FROM (select 원하는컬럼1, 원하는컬럼2, 원하는컬럼3 FROM 테이블명 ORDER BY boardno DESC) A)
WHERE R BETWEEN startNum and endNum;
복잡하게 느껴진다면 다음의 쿼리문을 그냥 사용해도 되지만 저는 공부하는 입장이기 때문에 위의 쿼리문을 분석해 보도록 하겠습니다.
2.쿼리문 분석
SELECT boardno,title,wdate FROM A WHERE R BETWEEN 1 and 10;
이 쿼리문을 보면 A가 무엇인지 R이 무엇인지 알수 없습니다. 그럼 먼저 A와 R이 무엇인지 알아야 합니다.
SELECT ROWNUM R, A.* FROM
(select boardno, title, wdate FROM board ORDER BY boardno DESC) A
다음을 통해 A는 boardno, title, wdate를 내림차순으로 정렬한 것이고, R은 ROWNUM을 가리킨다는 것을 알 수 있습니다.
ROWNUM은 오라클의 의사컬럼(Paseudo columns)입니다. 의사컬럼이란 테이블에 있는 일반적인 컬럼처럼 행동하기는 하지만 실제로 테이블에 저장되어 있지 않은 컬럼을 말합니다. 그러한 의사컬럼중에 ROWNUM은 쿼리의 결과로 나오게 되는 각각의 로우들에 대한 순서값을 가리키는 것입니다. ROWNUM은 주로 특정 개수나 그 이하의 로우를 선택할때 사용됩니다.
SELECT 컬럼명1, 컬럼명2, ROWNUM
FROM 테이블명
WHERE ROWNUM <= 10
위의 커리문은 테이블에 있는 컬럼1, 컬럼2을 10개까지 나타내는데 사용합니다.
이제 다음의 쿼리문을 분석해 보겠습니다.
SELECT ROWNUM R, A.* FROM
(select boardno, title, wdate FROM board ORDER BY boardno DESC) A
SELECT boardno,title,wdate FROM A WHERE R BETWEEN 1 and 10;
내림차순으로 정렬된 A에서 각 컬럼을 불러옵니다. 하지만 조건절이 있어 컬럼이 1부터 10 사이에 있는것만을 불러내는 것입니다.
3. list.jsp 만들기
위의 커리문이 만들어졌다고 끝이 아닙니다. list에서 원하는 형태를 불러내주어야 합니다.
int curPage = (request.getParameter("curPage") == null) ? 1 : Integer.parseInt(request.getParameter("curPage")); // 시작 레코드 계산 int startNum = (curPage - 1) * 10 + 1; // 마지막 레코드 계산 int endNum = startNum + 10 -1; // 해당 페이지의 레코드 셋을 구한 후 출력합니다. ... sql = "SELECT boardno,title,wdate FROM( " + "SELECT ROWNUM R, A.* FROM( select boardno, title, wdate " + "FROM board ORDER BY boardno DESC) A) " + "WHERE R BETWEEN " + startNum + " and " + endNum; ...
이제 list.jsp?curPage=2 라고 방문하면 11번부터 20번까지의 목록을 볼수 있습니다. 그냥 list.jsp를 방문해도 자동으로 curPage가 null이면 1로 바꿔주어 첫페이지를 볼수 있습니다.
여기서는 한페이지당 10개의 목록만을 나타내 주었지만 10이 아닌 다른 숫자로 선언한다면 얼마든지 원하는 목록의 갯수를 받을수 있습니다.
이것을 응용하여 <a href="list.jsp?curPage=1>[1]</a>라고 게시판 리스트를 만들어주면 됩니다.
4. 페이지 분할 알고리즘
이제 지금까지의 방식으로 모든것이 준비 되었습니다. 이제 페이지를 분할하는 알고리즘에 대해 생각해볼 차례 입니다. 페이지 분할은 다음의 알고리즘으로 만들어 주면 됩니다.
1. 총 레코드를 구한다.
2. 한페이지당 보일 레코드수를 구하고, 총 페이지를 정한다.
3. 첫레코드와 마지막 레코드의 번호를 구하고 출력한다.
4. 각 페이지에 대한 직접 링크를 만들어 준다.
총 레코드를 구해주는 이유는 페이지수를 구해주기 위해서 입니다. 따라서 가장 먼저 총 레코드를 구해줍니다.
totalRecord
int totalRecord;
String sql = "select count(*) cnt from board";
...
int totalRecord;
String sql = "select count(*) cnt from board";
...
위의 sql문을 통해 board의 총 레코드 수를 구할수 있습니다. 그 레코드를 통해 총 페이지를 구할수 있습니다.
totalPage
int totalPage = 0;
int numPerPage = 10;
if ( totalRecord != 0 ) {
if (( totalRecord % numPerPage) == 0 ) {
totalPage = ( totalRecord / numPerPage );
} else {
totalPage = ( totalRecord / numPerPage+ 1);
}
}
int totalPage = 0;
int numPerPage = 10;
if ( totalRecord != 0 ) {
if (( totalRecord % numPerPage) == 0 ) {
totalPage = ( totalRecord / numPerPage );
} else {
totalPage = ( totalRecord / numPerPage+ 1);
}
}
위 코드는 한페이지당 10개씩 보이디록 짠 프로그램입니다. numPerPage를 바꾸어주면 20개, 30개씩 보이게도 할 수 있습니다. 총레코드를 10으로 나누어 0으로 나누어 떨어지지 않을때에는 한 페이지가 더 있는 것이기 때문에 else문에서 1을 더해준것입니다.
링크 코드 작성
<%
for ( int i = 1; i<=totalPage; i++ ) {
%>
<a href="list.jsp?curPage=<%=i%>">[<%=i%>]</a>
<%
} // for statment end
%>
<%
for ( int i = 1; i<=totalPage; i++ ) {
%>
<a href="list.jsp?curPage=<%=i%>">[<%=i%>]</a>
<%
} // for statment end
%>
다음과 같은 방식으로 링크를 바로 이동할수 있는 코드를 만들어 줍니다. 그럼 curPage의 숫자에 맞는 리스트의 startNum과 endNum을 구해주어야 합니다.
리스트 레코드 코드 변경
int numPerPage = 10; // 시작 레코드 계산 int start = ( curPage - 1 ) * numPerPage + 1; // 마지막 레코드 계산 int end = start + numPerPage - 1;
5. list.jsp 코드 구현
위의 코드를 통합하여 간단한 list.jsp를 구현해 보았습니다.
<%@ page contentType="text/html;charset=euc-kr" %>
<%@ page import="java.sql.*,myjava.beepurple.*" %>
<jsp:useBean id="dbmgr" scope="application"
class="myjava.beepurple.db.dbpool.OracleConnectionManager" />
<html>
<body>
<%
Log log = new Log();
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = null;
//1. 총 레코드 수를 구한다.
int totalRecord = 0; //총 데이터 개수를 저장할 변수
try {
con = dbmgr.getConnection();
sql = "select count(*) cnt from board";
pstmt = conn.prepareStatement( sql );
rs = pstmt.executeQuery();
rs.next();
totalRecord = rs.getInt(1);
} catch ( SQLException e ) {
} finally {
try {
rs.close();
pstmt.close();
dbmgr.freeConnection( con );
//log.close();로그파일의 파일 출력 스트림을 반환하지 않는다.
} catch ( SQLException e ) {}
}
//2. 한 페이지당 보일 레코드 수를 결정하고, 총 페이지 수를 구한다.
int numPerPage = 10; // 한 페이지당 보일 레코드 수 결정
int totalPage = 0; //총 페이지수를 저장할 변수
if ( totalRecord != 0 ) {
if ( ( totalRecord % numPerPage ) == 0 ) {
totalPage = ( totalRecord / numPerPage );
} else {
totalPage = (totalRecord / numPerPage + 1 );
}
}
//3. 첫번째 레코드 번호와 마지막 레코드 번호를 구하고 출력한다.
int curPage = (request.getParameter("curPage") == null) ? 1 :
Integer.parseInt(request.getParameter("curPage"));
// 시작 레코드 계산 .....
int start = ( curPage - 1 ) * numPerPage + 1;
// 마지막 레코드 계산 .....
int end = start + numPerPage - 1;
// 해당 페이지의 레코드 셋을 구한 후 출력합니다.
try {
con = dbmgr.getConnection();
sql = "SELECT boardno,title,wdate FROM(" +
"SELECT ROWNUM R, A.* FROM(" +
"SELECT boardno, title, wdate FROM board ORDER BY boardno DESC) A) " +
"WHERE R BETWEEN ? and ?";
pstmt = con.prepareStatement( sql );
pstmt.setInt(1, start);
pstmt.setInt(2, end);
rs = pstmt.executeQuery();
while ( rs.next() ) {
int boardno = rs.getInt( "boardno" );
String title = rs.getString( "title" );
Date wdate = rs.getDate( "wdate" );
%>
<a href="view.jsp?boardno=<%=boardno%>&curPage=<%=curPage%>"><%=title%></a>
<%= wdate.toString() %><br>
<%
} //while 문 끝
} catch ( SQLException e ) {
log.debug( "Error Source:list.jsp : SQLException" );
log.debug( "SQLState : " + e.getSQLState() );
log.debug( "Message : " + e.getMessage() );
log.debug( "Oracle Error Code : " + e.getErrorCode() );
log.debug( "sql : " + sql );
} finally {
try {
rs.close();
pstmt.close();
dbmgr.freeConnection( con );
log.close();
} catch ( SQLException e ) {}
}
%>
<br>
<%
// 4. 각 페이지에 대한 직접 이동 링크를 만든다.
for ( int i = 1;i <= totalPage;i++ ) {
%>
<a href="list.jsp?curPage=<%= i %>"><%= i %></a>
<%
}
%>
<br>
<p>
<a href="write_form.jsp?curPage=<%=curPage%>">새글 쓰기</a>
</body>
</html>'Oracle & JSP & JDBC' 카테고리의 다른 글
| 페이지 분할 기능 (0) | 2008/11/19 |
|---|---|
| Apache Tomcat 설치 (0) | 2008/11/06 |
| 오라클 우편번호 데이터베이스 만드는 법 (2) | 2008/10/29 |
| 오라클 사용자 명령어 (0) | 2008/10/28 |
| JDBC 프로그래밍 방법 (0) | 2008/10/28 |
| 오라클 JDBC 드라이버 설치 및 테스트 (0) | 2008/10/28 |

Prev
Rss Feed