준형,유진,소윤이네 홈페이지
| Home | 자유게시판 | 최근소식 | 추억속으로 | 준형엄마 수다방 | 가족앨범 | 자료실 | 준형아빠 공부방 | 방명록

 가족
 친구 홈페이지 Link

날 씨


준형아빠 공부방

0
 17   2   1
  View Articles

Name  
   준형아빠 
Subject  
   CachedRowSetReader 사용방법
제 블로그에 있는 내용 긁어 왔습니다.
아래 스크랩한글에 나름대로 정리한 한글판.. 영어를 잘해서 한글판을 만든게 아니고 영어를 몰라서 나처럼 짜증나 하는 사람이 있을까봐서.. ㅠㅠ
일단 JDBC의 데이터베이스 연결하는 예를 하나...Connection Pool이용
* 예외 처리는 생략 했으므로 실제 사용시 예외처리 해줘야 함, 예제는 tomcat사용시,, 다른WAS도 비슷할거라 생각됨, client에서 사용시에도 db 연결하는 부분만 다르고 나머지 는 같음

import java.sql.*;
import javax.sql.*;
import javax.naming.*;

Connection conn ;
//Statement stmt;       //Statement 보다는 PreparedStatement 를 사용하는게 여러모로 좋음
PreparedStatement pstmt;
ResultSet rs ;  
Context initial = new InitialContext();
DataSource ds = (DataSource)initial.lookup("java:comp/env/jdbc/zpprd");  //server.xml에 정의된 데이터베이스 접속 정보를 읽어옴
conn = ds.getConnection();  //데이터베이스에 접속

pstmt=conn.prepareStatement("select * from EMP where JOB=? and DEPTNO=?");
pstmt.setString(1,"CLERK");   //첫번째 ?에 들어갈 문자열 1부터 시작됨(이제까지 프로그래밍하면 0부터 시작하는경우가 많았는데 하여튼 헛갈린다, 실제 소스를 보면 0부터 시작해서 +1 해주고 있다.)
pstmt.setInt(2,20);                //두번째 ?에 들어갈 숫자
rs = pstmt.executeQuery();
//이렇게 얻어온 쿼리 결과는 PreparedStatement 가 closed 되거나 Connection 이 closed 되면 데이터를 잃어 버린다.
MS의 ADO로 작업할때 커서 스타일이 cursorUseServer하고 비슷한 결과다.. 그러면 cursorUseClient와 비슷한결과를 얻고싶다면 즉 쿼리 결과를 Client?P으로 전부 가져온후에 바로 db 연결을 ConnectionPool에 반납하고 쿼리 결과를 가지고 화면에 뿌리거나 다른 클래스에 넘겨줄려면 어떻게 해야 할까..
바로 CachedRowSet을 이용하면 가능하다
일단 다운받은 CachedRowSet 클래스패스를 추가하고

import com.sun.rowset.*;     // 임포트해야 쓸수 있으니까..
DB연결해서 ResultSet 얻어오는건 위의 예제와 동일 하므로 생략

rs = pstmt.executeQuery();    //이렇게 얻어온 ResultSet 을
CachedRowSetImpl crs = new CachedRowSetImpl();
crs.populate(rs);                 //요 populate놈이 rs의 내용을 몽땅 crs로 복사한다.
그런후에
pstmt.close();  
con.close();
//위 두분도 역시 예외 처리 해줘야함(가비지 컬랙터가 자동으로 메모리 회수를 하지 못하므로 예외처리 특히 신경써야하는 부분)
pstmt가 close 됐지만 crs는 사용가능함.. 속성이나 메소드가 ResultSet 과 동일하므로 자세한 설명은 생략 ^^;

더 간단한 방법
import com.sun.rowset.*;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;

Connection conn ;
CachedRowSetImpl crs = new CachedRowSetImpl();

crs.setDataSourceName("java:comp/env/jdbc/zpprd");      //jabc/zpprd라는 이름으로 톰켓에 데이터 소스를 만듬
crs.setCommand("select * from EMP where JOB=? and DEPTNO=?");
crs.setString(1,"CLERK");
crs.setInt(2,20);
crs.execute();         // 지가 알아서 위에 정의한 데이터 소스 가지고 db 연결하고 쿼리 결과 가져오고 db 연결 close 함

이렇게만 코딩해도 crs가 ResultSet의 내용을 가져옴
그러면 내부적으로 어떻게 작동하는지 보자
PreparedStatement pstmt = con.prepareStatement(crs.getCommand());
    reader.decodeParams();
    // decodeParams figures out which setter methods to use and does something
    // like the following:
    //    for (i = 0; i < params.length; i++) {
    //        pstmt.setObject(i + 1, params[i]);
    //    }
ResultSet rs = pstmt.executeQuery();
crs.populate(rs);

영어가 좀있기는 하지만 동작 방식은 맨 처음 예제하고 동일하다.. 파라미터 값을 루프돌면서 가져와서 ResultSet 구하고 crs에 복사한다..(API 문서가 사실이라면 이렇게 잘 동작해야 한다..)
그런데 실제는 API 문서하고 좀 다르게 코딩이 되어있다..(jdbc_rowset-1_0-prd2-ri버전)
if(cachedrowset.getCommand().indexOf("?")==-1){           //여기서 ?이 있나 없나 검사해서 없으면
    ResultSet resultset=prepatedstatement.executeQuery();
    cachedrowset.populate(resultset);
    resultset.close();
}
else{           //있으면 executeUpdate를 실행해서 쿼리 결과가 않나온다..
    prepatedstatement.executeUpdate()
}

이문제로 몇일을 머리 싸매고 있었는데.. API문서에는 분명 아래 예제가 있는데..

    crs.setCommand("SELECT FIRST_NAME, LAST_NAME, ADDRESS FROM CUSTOMERS" +
                   "WHERE CREDIT_LIMIT > ? AND REGION = ?");
    crs.setInt(1, 5000);
    crs.setString(2, "West");
    crs.execute();
?표 생략하고 직접 변수값을 입력하면 결과가 잘나오고 그렇지 않으면 않나옴

방법은 두가지..
1. ? 파라미터 않쓰고 그냥 변수값을 sql 않에 넣어서 코딩하는 방법
2. sun 에서 제공하는 rowset의 CachedRowSetReader.class 파일을 변경한후 사용하는 방법

2004년 11월 1일 새버전(jdbc_rowset_tiger1.0.1mrel-spec) 발견 -- 위의 문제를 해결한 버전(처음 select로 시작하는지 검사)
CachedRowSet을 다운로드하는곳(최신 버전으로 다운받으면 됨)
http://java.sun.com/products/jdbc/download.html#rowset1_0_1
다운로드해서 압축해제 하면 API 문서 나오므로 API 문서 참조하면 될듯
http://java.sun.com/j2se/1.5.0/docs/api/javax/sql/rowset/CachedRowSet.html


2004년 11월 5일 새버전에 대한 문제점 해결
- 위에 버전을 다운받아 실행하면 Null Exception이 발생하거나 init 에러(초기화시 바로 에러 떨어짐) 등등 이 발견되어서 이것 저것 해본결과  Oracle JDBC 10g JDBC Driver 사용시 정상 동작
oracle jdbc driver은 otn.oracle.co.kr에서 다운받고,
JDK 버전도 1.5를 사용해야 정상동작
ojdbc14.jar,ojdbc14_g.jar(디버깅시 사용된네을 tomcat의 common/lib 폴더에 복사해 놓으면 됨, ocrs12.jar파일은 오라클에서 구현해 놓은 CachedRowSet인데.. 아직 구버전을 사용하는지 구버전 과 동일한 에러 발생(java.lang.UnsupportedOperationException )

참고로 오라클에서 구현해 놓은 CachedRowSet사용방법
import oracle.jdbc.rowset.*;
OracleCachedRowSet crs=new OracleCachedRowSet();
나머지 방법은 동일하므로 생략 ^^'

2004년 11월 10일 문제발생
DB Connection을 ConnectionPool에 반납을 못해서
org.apache.commons.dbcp.SQLNestedException: Cannot get a connection, pool exhausted, cause: Timeout waiting for idle object  라는 에러 발생
원인을 보면 놀고있는 오브젝트(connection)을 찾지 못했다고 하는데..  내부 소스는 제대로 close 하는데.. 원인을 못찾겠음..
임시 방편으로
crs.execute(conn);  //실행시 connection 객체를 넘겨주는 방법을 선택(DB연결부분 코딩 덜할려구 했는데.. 갈수록 소스가 지저분해지는것 같은...


Name
Memo
Password
 
     
Prev
   Raw/Long Raw Type에 관하여

준형아빠
Next
   [룰 엔진 Rule Engine]

준형아빠


Copyright 1999-2021 Zeroboard / skin by Zetyx
   Copyright ⓒ 2003.5.1 Kim,sun-hak. All rights reserved. h9841150@empal.com