본문 바로가기
Java

[JAVA] Chapter 13. CallableStatement

by nyeoo 2023. 12. 8.

1. CallableStatement

  • CallableStatement 인터페이스는 모든 DBMS 들에 대한표준 방법으로 저장 프로시저(stored procedure)를 호출하는 방법을 제공하는 인터페이스이며, 호출은 escape 문법으로 작성됨
  • 결과 매개변수를 가지는 형태, 결과 매개변수가 없는 형태(두 가지)이며 OUT 매개변수의 종류인 결과 매개변수는 저장 프로시저에 대한 반환값. 두 형태 모두 IN 매개변수(입력), OUT 매개변수(출력), INOUT 매개변수(입출력)를 위해 사용되는 매개변수의 변수 번호를 가지며 『?』는 매개변수의 저장 위치로 나타냄

형식 및 구조 (JDBC 에서 저장 프로시저 호출을 위한 문법)

  • 매개변수가 없는 저장 프로시저 호출
    {call procedure_name}
  • IN 매개변수를 반환하는 프로시저 호출
    {call procedure_name[(?, ?, ...)]}
  • OUT 매개변수를 반환하는 프로시저 호출 / 반환자료형이 존재하는 함수 호출
    {? = call procedure_name[(?, ?, ...)]}

2. CallableStatement 객체 생성

  • CallableStatement 객체는 Connection 의 prepareCall() 메소드에 의해 생성됨. 예를 들어, 두 개의 인자값을 가지고 있으며 결과 매개변수가 없는 저장 프로시저 prcData 를 호출하는 방법
    CallableStatement cstmt = conn.prepareCall("{call prcData(?, ?)}");

※ 물음표(『?』) 의 위치가 IN, OUT, INOUT 매개변수 중 어떤 것인가 하는 것은 저장 프로시저 prcData에 의존함

3. IN, OUT 매개변수

  • CallableStatement 객체로 IN 매개변수를 넘겨주는 것은 PreparedStatement 로 부터 상속받은 setXxx() 메소드 (ex. setFloat() 메소드는 float 값을 넘겨줌)
  • 저장 프로시저가 OUT 매개변수를 반환한다면 각 OUT 매개변수의 SQL 형(Type)은 CallableStatement 객체를 실행할 수 있는 상태가 되기 전에 등록되어져야 함. 이는 몇 몇 DBMS 들이 SQL 형(Type)을 필요로 하기 때문이며 이 때, SQL 형(Type)을 등록하는 것은 registerOutParameter() 메소드를 사용하게 됨
  • SQL 구문이 실행되어진 다음에 CallableStatement 의 getXxx() 메소드는 매개변수의 값을 검색하며, 사용되는 정확한 getXxx() 메소드는 그 매개변수를 위해 등록되어진 SQL 에 상응하는 자바 형(Type)임. 즉, registerOutParameter() 메소드는 SQL 타입을 사용하고, getXxx() 메소드는 이것을 자바 타입으로 캐스트(Cast)하는 것
import java.sql.CallableStatement;
import java.sql.Connection;
import java.util.Scanner;

import com.util.DBConn;

public class Test001
{
    public static void main(String[] args)
    {
        try
        {
            Scanner sc = new Scanner(System.in);
            Connection conn = DBConn.getConnection();

            do
            {
                System.out.print("이름 입력(-1 종료) : ");
                String name = sc.next();

                if (name.equals("-1"))
                {
                    break;    
                }

                System.out.print("전화번호 입력 : ");
                String tel = sc.next();

                if (conn != null)
                {
                    System.out.println("데이터베이스 연결 성공~!!!");

                    try
                    {
                        // 쿼리문 준비 (작업객체를 생성하기 전에 준비되어 있어야 한다~!!)
                        String sql = "{call PRC_MEMBERINSERT(?, ?)}";

                        // CallableStatement 작업 객체 생성 check~!!!
                        CallableStatement cstmt = conn.prepareCall(sql);

                        // 매개변수 전달
                        cstmt.setString(1, name);
                        cstmt.setString(2, tel);

                        int result = cstmt.executeUpdate();

                        if (result > 0)
                        {
                            System.out.println("프로시저 호출 및 데이터 입력 완료~!!!");

                        }

                    } catch (Exception e)
                    {
                        System.out.println(e.toString());
                    }
                }

            } while (true);

            DBConn.close();

            System.out.println("\n데이터베이스 연결 종료~!!!");
            System.out.println("프로그램 종료됨~!!!");

        } catch (Exception e)
        {
            System.out.println(e.toString());
        }
    }

}
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;

import com.util.DBConn;
import oracle.jdbc.OracleTypes;

public class Test002
{
    public static void main(String[] args)
    {
        try
        {
            Connection conn = DBConn.getConnection();

            if (conn != null)
            {
                System.out.println("데이터베이스 연결 성공~!!!");

                try
                {
                    // 쿼리문 준비
                    String sql = "{call PRC_MEMBERSELECT(?)}";


                    // CallableStatement 작업 객체 생성
                    CallableStatement cstmt = conn.prepareCall(sql);

                    // 프로시저 내부에서 sys_refcursor 를 사용하고 있기 때문에
                    // OracleTypes.CURSOR 를 사용하기 위한 등록과정이 필요한 상황
                    // 1. Project Explorer 상에서 해당 프로젝트(JDBC08) 마우스 우클릭
                    // 2. Build Path > Configure Build Path 클릭.
                    // 3. Libraries 탭 선택
                    // 4. 우측 Add External JAR 버튼 클릭
                    // 5. ojdbc6.jar 파일 추가 등록 (외부 jar 파일 연결)
                    // 6. 『import oracle.jdbc.OracleTypes;』 구문 추가 등록
                    cstmt.registerOutParameter(1, OracleTypes    .CURSOR);
                    cstmt.execute();
                    ResultSet rs = (ResultSet)cstmt.getObject(1);

                    while (rs.next())
                    {
                        String sid = rs.getString("SID");
                        String name = rs.getString("NAME");
                        String tel = rs.getString("TEL");

                        String str = String.format("%3s %7s %12s", sid, name, tel);
                        System.out.println(str);

                    }
                    rs.close();
                    cstmt.close();


                } catch (Exception e)
                {
                    System.out.println(e.toString());
                }
            }

            DBConn.close();
            System.out.println("데이터베이스 연결 닫힘~!!!");
            System.out.println("프로그램 종료됨~!!!");

        } catch (Exception e)
        {
            System.out.println(e.toString());
        }
    }

}