[JDBC] 05 ResultSet

프로그래밍/DB 2007. 11. 27. 13:58 Posted by galad

★ ResultSet

DB에 JDBC 드라이버를 이용하여 SQL의 수행을 요청하고 결과를 받아 내는 인터페이스이다.
JDBC 2.0 API에는 SQL 수행 결과를 스크롤되는 ResultSet으로도 저장할 수 있도록 한다.
 
next() - 다음 데이터
previous() - 이전 데이터
first() - 맨 처음 데이터
last() - 맨 마지막 데이터
beforeFirst()  - 제일 처음 위치
afterLast() - 맨 마지막 위치
absolute(int row) - 절대 위치로 간다. 시작부터 계산해서 row행으로.
relative(int row)  - 현재 위치를 기준으로 이동한다.
                                    현재 위치 + row행으로.
deleteRow()
insertRow()
  updateRow()
……
……
 
ScrollableResultSet :
     ResultSet을 스크롤 가능하게 만들어 커서를 원하는 레코드로 옮길 수도 있다.(JDBC 2.0)

UpdateableResultSet :
     ResultSet에서의 데이터 변경을 데이터베이스에 반영하도록 하는 기능을 제공.(JDBC 2.0)
 
 ■ ResultSet.TYPE_SCROLL_SENSITIVE
     ResultSet스크롤 가능하며 업데이트가 발생하면 바로 데이터베이스에 반영된다.

 ■ ResultSet.TYPE_SCROLL_INSENSITIVE
     ResultSet스크롤 가능하며 업데이트가 발생해도 데이터베이스에 반영되지 않는다.

 ■ ResultSet.TYPE_FORWARD_ONLY
     ResultSet 스크롤이 되지 않으며 다음 Row만 진행된다.
        Default값.

 ■ ResultSet.CONCUR_UPDATABLE
     ResultSet에서 데이터 변경을 가능하도록 설정한다.

 ■ ResultSet.CONCUR_READ_ONLY
     ResultSet에서 데이터 변경을 불가능하고 조회만 가능하도록 설정한다.
        Default값.
 
 


/******************************************************************************
*   파일      : RS_Scroll.java
*   용도      : ResultSet 을 Scroll 가능하게 해서 테스트하는 예제
*   작성자   : 성홍제
*   작성일   : 2006. 07. 27
*   Version : 1.0
******************************************************************************/

package ResultSet;

import java.sql.*;

import ConnectionPool.DBConnectionMgr;

public class RS_Scroll
{

    /**
     * @param args
     */
    public static void main(String[] args)
    {
        // TODO Auto-generated method stub
        DBConnectionMgr mgr = DBConnectionMgr.getInstance();
       
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        String sql = "select * from test10_tbl";
       
        try
        {
            conn = mgr.getConnection();
            pstmt = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE,

                                                         ResultSet.CONCUR_UPDATABLE);
            /*
             * ResultSet_Type                       ResultSet_Concurrency
             * TYPE_FORWARD_ONLY              CONCUR_READ_ONLY
             * TYPE_SCROLL_INSENSITIVE       CONCUR_UPDATABLE
             * TYPE_SCROLL_SENSITIVE
             */
           
            rs = pstmt.executeQuery();
           
            // rs를 맨 위에서부터 순차적으로 탐색한다.
            while(rs.next())
            {
                String s = "num: " + rs.getInt("num") + "\t" + "id: " + rs.getString("id") + "\t"

                             + "name: " + rs.getString("name") + "\t" + "age: " + rs.getInt("age");
                System.out.println(s);
            }
            System.out.println("순차탐색 끝");
           
            // rs가 afterLast에 있지않으면 - afterLast로 보낸다.
            if(rs.isAfterLast())
                rs.afterLast();
           
            // rs를 맨 밑에서부터 역순으로 탐색한다.
            while(rs.previous())
            {
                String s = "num: " + rs.getInt("num") + "\t" + "id: " + rs.getString("id") + "\t"

                             + "name: " + rs.getString("name") + "\t" + "age: " + rs.getInt("age");
                System.out.println(s);
            }
           
            System.out.println("역순탐색 끝");
           
            // rs를 5번째 행으로 보낸다. 절대위치로 이동
            rs.absolute(5);
           
            // 5번으로 이동한 후, 그 이전 것 즉, 4번부터 출력한다.
            while(rs.previous())
            {
                String s = "num: " + rs.getInt("num") + "\t" + "id: " + rs.getString("id") + "\t"

                             + "name: " + rs.getString("name") + "\t" + "age: " + rs.getInt("age");
                System.out.println(s);
            }
            System.out.println("절대위치로 이동후, 역순으로 탐색 끝");
           
            // 맨 위로 이동해 있는 rs를 상대적으로 이동시키려 했으나, 오류 발생
            // java.sql.SQLException: 현재 행이 아닙니다: relative - 맨 위로 이동해서 현재 위치가

            // beforeFirst라서 데이터가 없으므로 상대적으로 이동불가
            // 따라서 rs.next를 해서 데이터가 있는 곳으로 간 뒤, 상대적으로 이동시킨다.
            rs.next();           // 현재 위치 1번.
            rs.relative(7);     // 상대적으로 7칸 이동. 현재 위치 8번
            rs.relative(-3);    // 다시 위로 3칸 이동. 현재 위치 5번.
           
            // 5번 다음 것부터 출력하므로 6번부터 나온다.
            while(rs.next())
            {
                String s = "num: " + rs.getInt("num") + "\t" + "id: " + rs.getString("id") + "\t"

                             + "name: " + rs.getString("name") + "\t" + "age: " + rs.getInt("age");
                System.out.println(s);
            }
           
            pstmt.close();
            conn.close();
            mgr.freeConnection(conn);
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}


★ ResultSet의 TYPE_SCROLL_INSENSITIVE, TYPE_SCROLL_SENSITIVE, 

    CONCUR_UPDATABLE에 대해서


① stmt1(Statement개체)이 ResultSet을 INSENSITIVE, UPDATABLE로 생성한 후, 사용하는 경우

stmt1은 rs를 통해서 DB를 업데이트 할 수 있다.

하지만, stmt2(즉 다른 사용자라고도 볼 수 있는)가 DB를 바꾸었을 때, 그 바뀐 내용을 가져오지는못한다.

그래서

② SENSITIVE 옵션이 필요하다.

SENSITIVE 옵션을 주어 생성한 rs는 변경된 DB의 내용을 가져올 수 있다.

하지만, refreshRow() 메소드는 각 행별로 변경된 내용을 가져오므로, 미리 가져와서 사용하고 있는 rs의 행의 수와 변경된 DB의 행의 수가 다를 경우에는 문제가 생긴다.



/******************************************************************************
*   파일      : RS_InDel.java
*   용도      : ResultSet을 Update가능하게 해서 테스트하는 예제
*   작성자   : 성홍제
*   작성일   : 2006. 07. 27
*   Version : 1.0
******************************************************************************/

package ResultSet;

import java.sql.*;

import ConnectionPool.DBConnectionMgr;

public class RS_InDel
{

    /**
     * @param args
     */
    public static void main(String[] args)
    {
        // TODO Auto-generated method stub
        DBConnectionMgr mgr = DBConnectionMgr.getInstance();
       
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        String sql = "select num, id, name, age from test10_tbl";
       
        try
        {
            conn = mgr.getConnection();
            pstmt = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE,

                                                         ResultSet.CONCUR_UPDATABLE);
            /*
             * ResultSet_Type                       ResultSet_Concurrency
             * TYPE_FORWARD_ONLY              CONCUR_READ_ONLY
             * TYPE_SCROLL_INSENSITIVE       CONCUR_UPDATABLE
             * TYPE_SCROLL_SENSITIVE
             */
           
            rs = pstmt.executeQuery();
       
            // String sql = "select * from test10_tbl";

            // - 데이터를 추가하기 위해서는 컬럼명을 직접 입력해줘야 한다.
            // 이렇게 *로 하면 인식 못한다.
            // 데이타 추가 ------------------------------------------------------

            // 데이터를 추가하기 위해서 데이터 추가가 가능한 ROW로 이동. 맨 밑.
            rs.moveToInsertRow();      
            rs.updateInt (1, 1001);
            rs.updateString (2, "ID44");
            rs.updateString (3, "JUNG");
            rs.updateInt (4, 71);
            rs.insertRow();     // 데이터를 추가한다. DB도 변경된다.
           
            rs.moveToInsertRow();
            rs.updateInt (1, 1002);
            rs.updateString (2, "ID66");    // 2번까지만 넣어주면, 나머지는 이전에 사용했던 것들,
                                                     // 즉 (3, JUNG), (4, 71) 값이 들어가게 된다.
            rs.insertRow();
                   
            //rs.close ();  // 여기서 close 해버리면 밑에서 rs를 다시 얻기 전에는 사용불가.
            //------------------------------------------------------------------
           
            System.out.println ("데이타 추가 후 =============");
           
            System.out.println ("지금 쓰고 있는 rs의 내용-----");
            rs.beforeFirst();
            while(rs.next())
            {
                String s = "num: " + rs.getInt("num") + "\t" + "id: " + rs.getString("id") + "\t"

                           + "name: " + rs.getString("name") + "\t" + "age: " + rs.getInt("age");
                System.out.println(s);
            }
            // rs는 변경되었고 UPDATABLE 옵션이 있었으므로 DB도 변경되었다.
           
            rs.close ();
           
            System.out.println ("DB의 내용을 다시 받아온다.-----");
            rs = pstmt.executeQuery();
            while(rs.next())
            {
                String s = "num: " + rs.getInt("num") + "\t" + "id: " + rs.getString("id") + "\t"

                           + "name: " + rs.getString("name") + "\t" + "age: " + rs.getInt("age");
                System.out.println(s);
            }
            // DB의 내용이 변경된 것을 볼 수 있다.
           
            // 데이타 삭제 -----------------------------------------------------
            if (!rs.isBeforeFirst())   
            {
                rs.beforeFirst();
            }
           
            while (rs.next())  
            {
                if (rs.getInt(1) == 1001)
                {
                    rs.deleteRow();
                    break;
                }
            }
            //rs.close ();
            //-----------------------------------------------------------------
           
            System.out.println ("데이타 삭제 후============ ");
           
            System.out.println ("지금 쓰고 있는 rs의 내용-----");
            rs.beforeFirst();
            while(rs.next())
            {
                String s = "num: " + rs.getInt("num") + "\t" + "id: " + rs.getString("id") + "\t"

                            + "name: " + rs.getString("name") + "\t" + "age: " + rs.getInt("age");
                System.out.println(s);
            }
            // 역시 마찬가지로 rs는 변경되었고 UPDATABLE 옵션이 있었으므로 DB도 변경되었다.
           
            //rs.close ();
           
            System.out.println ("DB의 내용을 다시 받아온다.-----");
            rs = pstmt.executeQuery();
            while(rs.next())
            {
                String s = "num: " + rs.getInt("num") + "\t" + "id: " + rs.getString("id") + "\t"

                            + "name: " + rs.getString("name") + "\t" + "age: " + rs.getInt("age");
                System.out.println(s);
            }
            // DB의 내용이 변경된 것을 볼 수 있다.
           
            // 테이블 원상태로 복원 -------------------------------------------
            // 새롭게 생성한 stmt1이 DB의 내용을 변경한다.
            // 이렇게 변경된 DB의 내용은 지금은 rs에 반영할 수 없다. SENSITIVE 옵션이 없으므로.
            // 하지만 stmt가 사용하던 rs의 내용이 변경되지 않았다고 하더라도

            // DB는 이미 변경된 상태이므로
            Statement stmt1 = conn.createStatement ();
            stmt1.execute("DELETE FROM test10_tbl WHERE num=1001 OR num=1002");
            //stmt1.execute("COMMIT");
            stmt1.close();
           
            System.out.println ("데이타 복원 후============ ");

            System.out.println ("지금 쓰고 있는 rs의 내용-----");
            rs.beforeFirst();
            while(rs.next())
            {
                String s = "num: " + rs.getInt("num") + "\t" + "id: " + rs.getString("id") + "\t"

                            + "name: " + rs.getString("name") + "\t" + "age: " + rs.getInt("age");
                System.out.println(s);
            }
            // stmt가 사용하던 rs의 내용은 그대로이다.
           
            rs.close ();
           
            System.out.println ("DB의 내용을 다시 받아온다.-----");
            rs = pstmt.executeQuery();
            while(rs.next())
            {
                String s = "num: " + rs.getInt("num") + "\t" + "id: " + rs.getString("id") + "\t"

                            + "name: " + rs.getString("name") + "\t" + "age: " + rs.getInt("age");
                System.out.println(s);
            }
            // stmt1이 변경한 이후의 DB의 내용이 새롭게 rs에 들어간다.
            // stmt1이 변경한 값이 DB에 반영되어 있는 것을 알 수 있다.
           
            pstmt.close();
            conn.close();
            mgr.freeConnection(conn);
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

'프로그래밍 > DB' 카테고리의 다른 글

[Oracle/펌] PL/SQL 01  (0) 2007.11.27
[JDBC] 06 PL/SQL  (0) 2007.11.27
[JDBC] 04 JDBC - Connection Pool...  (0) 2007.11.27
[JDBC] 03 3일째  (0) 2007.11.27
[JDBC] 02 2일째  (0) 2007.11.27