IT_Programming/Java

[JDBC] CallableStatement (Stored procedure)

JJun ™ 2007. 10. 28. 12:58
CallableStatement (Stored procedure)


CallableStatement 객체는 모든 DBMS들에 대한 표준방법으로 저장 프로시져(stored procedure)를

호출하는 방법을 제공한다. 저장 프로시져를 데이터베이스에 저장하고, 저장 프로시져의 호출은

CallableStatement 객체를 사용한다. 이러한 호출은 두가지 형태중의 하나인 escape 문법으로

작성되어진다. stored procedure는 두가지 형태가 존재 한다. 

1. result parameter가 있는 경우
2. result parameter가 없는 경우

 

두 형태 모두 입력(IN 매개변수), 출력(OUT 매개변수) , 또는 둘다(INOUT 매개변수)를 위해

사용되어지는 매개변수의 변수 번호를 가질 것이다. ?는 매개변수의 위한 저장위치로 취급된다. 

 

JDBC에서 저장 프로시져를 호출하기 위한 문법은 아래와 같다. "[ ]"내의 내용은 선택적이다.

 

        {call procedure_name[(?, ?, ...)]}


결과 매개변수를 리턴하는 프로시져를 위한 문법은 다음과 같다.:
        {? = call procedure_name[(?, ?, ...)]}

 

매개변수가 없는 저장 프로시져를 위한 문법은 다음과 같을 것이다. :
        {call procedure_name}

 

보통, CallableStatement 객체를 생성하는 사람은 이미 사용하는 DBMS가 저장 프로시져를 지원하고 그러한 프로시져들이 있는 곳을 안다는 것이다.
그러나 검사할 필요가 있다면, 다양한 DatabaseMetaData 메쏘드들을 사용하여 정보를 얻는다.
예를 들어, supportsStoredProcedures 메쏘드는 DBMS가 저장 프로시져 호출을 지원하면 true를

리턴하며, getProdedures 메쏘드는 유효한 저장 프로시져의 설명을 리턴한다. CallableStatement는 일반적으로 SQL문들을 처리하는 Statement 클래스를 상속받고, 또한 IN 매개 변수를 처리하는

PreparedStatement 메쏘드들을 상속받는다.
CallableStatement에 정의된 모든 메쏘드들은 OUT 매개변수들이나 INOUT 매개변수의 출력쪽을

처리한다. 즉, 이러한 메쏘드들은 OUT 매개변수의 SQL형들을 등록하거나, 그것들로부터 값들을

검색하거나, 리턴된 값이 SQL NULL 인지를 검사한다.


 

 

7.1.1. CallableStatement 객체 생성하기

CallableStatement 객체는 Connection의 prepareCall 메쏘드에 의해 생성된다.
아래의 예제는 저장 프로시져 getTestData의 호출을 포함하는 CallableStatement의 인스턴스를

만든다. 이것은 두 개의 인자들을 가지고 있고 결과 매개변수는 없다.:

        CallableStatement cstmt = con.prepareCall("{call getTestData(?, ?)}");
? 위치가 IN, OUT, 또는 INOUT 매개변수인지는 저장 프로시져 getTestData에 의존한다.

 

 


7.1.2 IN/OUT 매개변수들

CallableStatement객체로 IN 매개변수를 넘겨주는 것은 PreparedStatement로부터 상속받은 setXXX 메쏘드이다. 넘겨질 값의 데이터형은 사용할 setXXX 메쏘드를 결정한다.(setFloat는 float 값을 넘겨준다.등등) 만약 저장 프로시져가 OUT 매개변수를 리턴한다면, 각 OUT 매개변수의 SQL형은 CallableStatement 객체를 실행할 수 있기 전에 등록되어져야 한다.(이것은 몇몇 DBMS들이 SQL형을 필요로 하기 때문에 필요하다.) SQL형을 등록하는 것은 registerOutParameter 메쏘드를 사용한다.
그리고나서 SQL문이 실행되어진 다음에, CallableStatement의 getXXX 메쏘드는 매개변수 값을

검색한다. 사용하는 정확한 getXXX 메쏘드는 그 매개변수를 위해 등록되어진 SQL에 상응하는 자바형이다.(SQL형들을 자바형들로의 표준 매핑은 8.5.1장의 테이블에서 보여준다.)
바꾸어 말하면, registerOutParameter는 SQL형을 사용하고(데이터베이스가 리턴할 SQL형과 매칭하기위해서), getXXX는 이것을 자바형으로 캐스트(cast)한다. 다음의 코드는 OUT 매개변수들을 등록하고, cstmt에 의해 호출되는 저장 프로시져를 실행하고, 그런다음 OUT 매개변수들내에서 리턴된 값을 검색한다. getByte 메쏘드는 첫 번째 OUT 매개변수로부터 자바 byte를 검색하고, getBigDecimal은 두 번째 OUT 매개변수로부터 (소수점 뒤에 세 개의 숫자를 가진) BigDecimal 객체를 검색한다.:

        CallableStatement cstmt = con.prepareCall("{call getTestData(?, ?)}");
        cstmt.registerOutparameter(1, java.sql.Types.TINYINT);
        cstmt.registerOutparameter(2, java.sql.Types.DECIMAL, 3);
        cstmt.executeQuery();
        byte x = cstmt.getByte(1);
        java.math.BigDecimal n = cstmt.getBigDecimal(2, 3);
ResultSet와는 달리, CallableStatement는 점진적으로 큰 OUT값들을 검색하기 위한 특별한 메카니즘을 제공하지 않는다.

 

 


7.1.3 INOUT 매개변수들

출력을 받아들이고 입력도 공급하는 매개변수(INOUT 매개변수)는 PreparedStatement로부터 상속받은

적당한 setXXX메소드의 호출외에 registerOutParamter 메쏘드의 호출을 요구한다.
setXXX메쏘드는 매개변수의 값을 입력 매개변수로 설정하고 registerOutParameter는 그것의 SQL형을 출력 매개변수로 등록한다. setXXX 메쏘드는 드라이버가 SQL 값으로 변환된후에 데이터베이스로 전송할 자바 값을 제공한다. 이 IN값의 SQL형과 registerOutParameter 메쏘드에 공급되어지는 값은 같아야만한다. 그런다음 출력값을 검색하기위해서, 상응하는 getXXX 메쏘드를 사용한다.
예를 들어, 자바형이 byte인 매개변수는 입력값을 할당하기위해서 setByte 메쏘드를 사용하고, TINYINT를 registerOutParameter의 SQL형으로 공급하고, 출력값을 검색하기위해서 getByte를 사용해야한다. (자세한 내용은 8장 "SQL과 자바형들을 매핑하기"를 참조해라)


다음의 예제는 유일한 매개변수로 INOUT 매개변수를 가지고 있는 저장 프로시져 reviseTotal이 있다는 것을 가정한다. setByte 메쏘드는 매개변수를 25로 설정하며, 이것은 드라이버가 SQL TINYINT로써 데이터베이스에 전송할 것이다. 그런다음 registerOutParameter는 SQL TINYINT로써 매개변수를 등록한다. 저장 프로시져가 실행된 후에, 새로운 SQL TINYINT 값을 리턴하고, getByte 메쏘드는 이 새로운 값을 자바 byte로 검색할 것이다.

 

        CallableStatement cstmt = con.prepareCall("{call reviseTotal(?)}");
        cstmt.setByte(1, 25);
        cstmt.registerOutparameter(1, java.sql.Types.TINYINT);
        cstmt.executeUpdate();
        byte x = cstmt.getByte(1);

 

 

 

7.1.4 결과후에 OUT Parameter 검색

몇몇 DBMS들에 있는 제한 때문에, 최대이식성을 위해서 CallableStatement 객체의 실행에 의해 생성된 모든 결과들은 OUT 매개변수들이 CallableStatement.getXXX 메쏘드를 사용하여 검색되기전에 검색되어져야한다. 만약 CallableStatement 객체가 다중 ResultSet 객체들을 리턴한다면(execute 메쏘드 호출을 이용하여), 모든 결과들은 OUT 매개변수를 검색하기전에 검색되어질 것이다. 이러한 경우에, 모든 결과들이 접근되어지는 것을 확인하기위해서, Statement 메쏘드들 getResultSet, getUpdateCount, 그리고 getMoreResults는 더 이상의 결과가 없을때까지 호출되어져야한다. 이것을 실행한후에, OUT 매개변수들로부터의 값들은 CallableStatement.getXXX 메쏘드들을 사용하여 검색될 수 있다.

 

 


7.1.5 OUT 매개변수들로써 NULL 값들을 검색하기

OUT 매개변수로 리턴되는 값은 SQL NULL일 것이다. 이러한 것이 발생했을 때, SQL NULL 값은 getXXX 메쏘드에 의해 리턴된 값이 getXXX 메쏘드 형에 의존하여 null, 0 또는 false가 되도록 변환되어져야 한다. ResultSet 객체에서 처럼, 0 또는 false값이 원래 SQL NULL인지 알 수 있는 유일한 방법은 wasNull 메쏘드를 가지고 검사하는 것이다. wasNull 메쏘드는 getXXX 메쏘드에 의해 읽은 마지막 값이 SQL NULL 이면 true, 아니면 false를 리턴한다.  

 

그리고나서 SQL문이 실행되어진 다음에, CallableStatement의 getXXX 메쏘드는 매개변수 값을 검색한다. 사용하는 정확한 getXXX 메쏘드는 그 매개변수를 위해 등록되어진 SQL에 상응하는 자바형이다. 바꾸어말하면, registerOutParameter는 SQL형을 사용하고(데이터베이스가 리턴할 SQL형과 매칭하기위해서), getXXX는 이것을 자바형으로 캐스트(cast)한다.

다음의 코드는 OUT 매개변수들을 등록하고, cstmt에 의해 호출되는 저장 프로시져를 실행하고, 그런다음 OUT 매개변수들내에서 리턴된 값을 검색한다.
getByte 메쏘드는 첫 번째 OUT 매개변수로부터 자바 byte를 검색하고, getBigDecimal은 두 번째 OUT 매개변수로부터 (소수점 뒤에 세 개의 숫자를 가진) BigDecimal 객체를 검색한다.

 

        CallableStatement cstmt = con.prepareCall("{call getTestData(?, ?)}");
        cstmt.registerOutparameter(1, java.sql.Types.TINYINT);
        cstmt.registerOutparameter(2, java.sql.Types.DECIMAL, 3);
        cstmt.executeQuery();
        byte x = cstmt.getByte(1);
        java.math.BigDecimal n = cstmt.getBigDecimal(2, 3);

      ===============================================================================

    cStmt = conn.prepareCall("{call sp_BPMUserGroupupdate(?)}");
    cStmt.registerOutParameter(1, Types.VARCHAR);
    cStmt.execute();
 
    spReturn = cStmt.getString(1);

 

 


- INOUT 매개변수들
출력을 받아들이고 입력도 공급하는 매개변수(INOUT 매개변수)는 PreparedStatement로부터

상속받은 적당한 setXXX메소드의 호출외에 registerOutParamter 메쏘드의 호출을 요구한다.
setXXX메쏘드는 매개변수의 값을 입력 매개변수로 설정하고 registerOutParameter는 그것의

SQL형을 출력 매개변수로 등록한다.
setXXX 메쏘드는 드라이버가 SQL 값으로 변환된후에 데이터베이스로 전송할 자바 값을 제공한다.
이 IN값의 SQL형과 registerOutParameter 메쏘드에 공급되어지는 값은 같아야만한다.
그런다음 출력값을 검색하기위해서, 상응하는 getXXX 메쏘드를 사용한다.
예를 들어, 자바형이 byte인 매개변수는 입력값을 할당하기위해서 setByte 메쏘드를 사용하고, TINYINT를 registerOutParameter의 SQL형으로 공급하고, 출력값을 검색하기위해서 getByte를

사용해야한다.


다음의 예제는 유일한 매개변수로 INOUT 매개변수를 가지고 있는 저장 프로시져 reviseTotal이

있다는 것을 가정한다. setByte 메쏘드는 매개변수를 25로 설정하며, 이것은 드라이버가 SQL

TINYINT로써 데이터베이스에 전송할 것이다. 그런 다음 registerOutParameter는 SQL TINYINT로써

매개변수를 등록한다. 저장 프로시져가 실행된 후에, 새로운 SQL TINYINT 값을 리턴하고, getByte

메쏘드는 이 새로운 값을 자바 byte로 검색할 것이다.

        CallableStatement cstmt = con.prepareCall("{call reviseTotal(?)}");
        cstmt.setByte(1, 25);
        cstmt.registerOutparameter(1, java.sql.Types.TINYINT);
        cstmt.executeUpdate();
        byte x = cstmt.getByte(1);

 

 

 

 

 

예제1)
public static void setDeathAge(Poet dyingBard, int age)
    throws SQLException
{
   Connection con = null;
   CallableStatement proc = null;
   try
   {
      con  = connectionPool.getConnection();
      proc = con.prepareCall("{ call set_death_age(?, ?) }");
      proc.setString(1, dyingBard.getName());
      proc.setInt(2, age);
      proc.execute();
   }
   finally
   {
      try
      {
         proc.close();
      }
      catch (SQLException e) {}
      con.close();
   }
}

 

 

예제2)
connection.setAutoCommit(false);
CallableStatement proc =
    connection.prepareCall("{ ? = call snuffed_it_when(?) }");
proc.registerOutParameter(1, Types.INTEGER);
proc.setString(2, poetName);
cs.execute();
int age = proc.getInt(2);

 

 

예제3)

static void sendEarlyDeaths(PrintWriter out)
{
    Connection con = null;
    CallableStatement toesUp = null;
    try
    {
        con = ConnectionPool.getConnection();
        // PostgreSQL needs a transaction to do this...
        con.setAutoCommit(false);
        // Setup the call.
        CallableStatement toesUp
            = connection.prepareCall("{ ? = call list_early_deaths () }");
        toesUp.registerOutParameter(1, Types.OTHER);
        getResults.execute();
        ResultSet rs = (ResultSet) getResults.getObject(1);
        while (rs.next())
        {
            String name = rs.getString(1);
            int age = rs.getInt(2);
            out.println(name + " was " + age + " years old.");
        }
        rs.close();
    }
    catch (SQLException e)
    {
        // We should protect these calls.
        toesUp.close();
        con.close();
    }
}


------------------------------------------------------------------------------

 

참고)
http://blog.naver.com/ribido74/30016993351

 

참고)
http://publib.boulder.ibm.com/infocenter/cscv/v10r1/index.jsp?topic=/com.ibm.cloudscape.doc/rrefjdbc20485.html

CallableStatements and OUT Parameters
CallableStatements and INOUT Parameters

'IT_Programming > Java' 카테고리의 다른 글

signed applet 만들기  (0) 2007.11.22
Applet → Refference JavaScript  (0) 2007.11.22
초간단 ClassLoader 사용하기  (0) 2007.09.03
Java 관련 사이트  (0) 2007.08.23
Collection 클래스  (0) 2007.07.05