Computer >> 컴퓨터 >  >> 프로그래밍 >> MySQL

JDBC의 CallableStatement란? 저장 프로시저 호출 방법 완벽 정리


CallableStatement 인터페이스는 저장 프로시저(stored procedure)를 실행하기 위한 메서드를 제공합니다. JDBC API는 저장 프로시저용 SQL 이스케이프(escape) 문법을 표준으로 제공하기 때문에, 어떤 RDBMS를 사용하든 동일한 방식으로 저장 프로시저를 호출할 수 있습니다.

CallableStatement 생성하기

Connection 인터페이스의 prepareCall() 메서드를 사용하면 CallableStatement 객체를 생성할 수 있습니다. 이 메서드는 저장 프로시저를 호출하는 쿼리 문자열을 인자로 받고, 그 결과로 CallableStatement 객체를 반환합니다.

CallableStatement에는 입력(IN) 파라미터, 출력(OUT) 파라미터, 또는 둘 다 포함될 수 있습니다. 프로시저 호출 시 입력 파라미터를 전달하려면 먼저 플레이스홀더(?)를 지정한 뒤, CallableStatement 인터페이스가 제공하는 setter 메서드(setInt(), setString(), setFloat() 등)로 값을 바인딩하면 됩니다.

예를 들어 데이터베이스에 myProcedure라는 프로시저가 있다면 다음과 같이 callable statement를 준비할 수 있습니다.

// CallableStatement 준비
CallableStatement cstmt = con.prepareCall("{call myProcedure(?, ?, ?)}");

입력 파라미터 값 설정하기

setter 메서드를 사용하면 프로시저 호출에 필요한 입력 파라미터 값을 설정할 수 있습니다.

setter 메서드는 두 개의 인자를 받습니다. 첫 번째는 입력 파라미터의 위치 인덱스를 나타내는 정수이고, 두 번째는 프로시저에 전달할 int, String, float 등의 실제 값입니다.

참고: 인덱스 대신 파라미터 이름을 문자열로 전달하는 것도 가능합니다.

cstmt.setString(1, "Raghav");
cstmt.setInt(2, 3000);
cstmt.setString(3, "Hyderabad");

CallableStatement 실행하기

CallableStatement 객체를 생성했다면 execute() 계열의 메서드를 호출하여 실행할 수 있습니다.

cstmt.execute();

출력(OUT) 파라미터 처리하기

저장 프로시저가 값을 반환하는 경우에는 출력 파라미터를 사용합니다. 이때는 registerOutParameter() 메서드로 파라미터의 JDBC 타입을 미리 등록해야 하며, 프로시저 실행 후 getter 메서드(getInt(), getString() 등)로 결과를 읽어올 수 있습니다.

CallableStatement cstmt = con.prepareCall("{call getEmployeeName(?, ?)}");
cstmt.setInt(1, 101);                          // IN 파라미터
cstmt.registerOutParameter(2, Types.VARCHAR);  // OUT 파라미터 등록
cstmt.execute();
String name = cstmt.getString(2);              // 결과 값 읽기

실전 예제

MySQL 데이터베이스에 다음과 같은 데이터를 담은 Employee 테이블이 있다고 가정해 보겠습니다.

+---------+--------+----------------+
| Name    | Salary | Location       |
+---------+--------+----------------+
| Amit    | 30000  | Hyderabad      |
| Kalyan  | 40000  | Vishakhapatnam |
| Renuka  | 50000  | Delhi          |
| Archana | 15000  | Mumbai         |
+---------+--------+----------------+

그리고 이 테이블에 데이터를 삽입하는 myProcedure 프로시저를 아래와 같이 생성해 두었습니다.

CREATE PROCEDURE myProcedure (IN name VARCHAR(30), IN sal INT, IN loc VARCHAR(45))
BEGIN
    INSERT INTO Employee(Name, Salary, Location) VALUES (name, sal, loc);
END //

다음은 callable statement를 통해 위 프로시저를 호출하여 Employee 테이블에 새 레코드를 삽입하는 JDBC 예제입니다. 파라미터 값을 설정할 때마다 execute()를 호출해야 각 레코드가 정상적으로 반영됩니다.

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class CallableStatementExample {
    public static void main(String args[]) throws SQLException {
        // 드라이버 등록
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());

        // 데이터베이스 연결
        String mysqlUrl = "jdbc:mysql://localhost/testdb";
        Connection con = DriverManager.getConnection(mysqlUrl, "root", "password");
        System.out.println("Connection established......");

        // CallableStatement 준비
        CallableStatement cstmt = con.prepareCall("{call myProcedure(?, ?, ?)}");

        cstmt.setString(1, "Raghav");
        cstmt.setInt(2, 3000);
        cstmt.setString(3, "Hyderabad");
        cstmt.execute();

        cstmt.setString(1, "Kalyan");
        cstmt.setInt(2, 4000);
        cstmt.setString(3, "Vishakhapatnam");
        cstmt.execute();

        cstmt.setString(1, "Rukmini");
        cstmt.setInt(2, 5000);
        cstmt.setString(3, "Delhi");
        cstmt.execute();

        cstmt.setString(1, "Archana");
        cstmt.setInt(2, 15000);
        cstmt.setString(3, "Mumbai");
        cstmt.execute();

        System.out.println("Rows inserted ....");
    }
}

실행 결과

Connection established......
Rows inserted ....

select 쿼리로 Employee 테이블을 조회하면 새로 추가된 레코드를 확인할 수 있습니다.

mysql> SELECT * FROM employee;
+---------+--------+----------------+
| Name    | Salary | Location       |
+---------+--------+----------------+
| Amit    | 30000  | Hyderabad      |
| Kalyan  | 40000  | Vishakhapatnam |
| Renuka  | 50000  | Delhi          |
| Archana | 15000  | Mumbai         |
| Raghav  | 3000   | Hyderabad      |
| Kalyan  | 4000   | Vishakhapatnam |
| Rukmini | 5000   | Delhi          |
| Archana | 15000  | Mumbai         |
+---------+--------+----------------+
8 rows in set (0.00 sec)