「Java」JDBC 経由でストアドプロシージャを実行する

JDBC ドライバ経由で ( Oracle Database の ) ストアドプロシージャを実行するサンプルを書いてみたので、メモしておきます。

実行するストアドプロシージャは

■ 以下のエントリーの select_t1_1
・「Oracle」ストアドプロシージャを作成してみる - プログラム日記
http://a4dosanddos.hatenablog.com/entry/2015/05/08/010524

■ 以下のエントリーの select_t1_cursor
・「Oracle」ストアドプロシージャのカーソルを使ってみる - プログラム日記
http://a4dosanddos.hatenablog.com/entry/2015/05/08/012356

にしました。

以下がサンプルです。

package jdbc.test;

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

import oracle.jdbc.OracleTypes;

public class ProcedureCallTest {
	public static void main(String[] args) {
		test1();
		//test2();
	}

	private static void test1() {
		String sql = "{call select_t1_1(?,?,?)}";
		try (Connection con = getConnection();
				CallableStatement cs = con.prepareCall(sql);) {
			cs.setInt(1, 1);
			cs.registerOutParameter(2, Types.INTEGER);
			cs.registerOutParameter(3, Types.VARCHAR);
			cs.executeQuery();
			System.out.println("id   : " + cs.getInt(2));
			System.out.println("name : " + cs.getString(3));
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	private static void test2() {
		String sql = "{call bbb.select_t1_cursor(?,?)}";
		try (Connection con = getConnection();
				CallableStatement cs = con.prepareCall(sql);) {
			cs.setString(1, "aaa");
			cs.registerOutParameter(2, OracleTypes.CURSOR);
			cs.executeQuery();
			try (ResultSet rs = (ResultSet) cs.getObject(2);) {
				while (rs.next()) {
					System.out.println("-----");
					System.out.println("id   : " + rs.getInt(1));
					System.out.println("name : " + rs.getString(2));
				}
			} catch (SQLException e) {

			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	private static Connection getConnection() {
		String className = "oracle.jdbc.driver.OracleDriver";
		String url = "jdbc:oracle:thin:@***.***.***.***:1521:orcl";
		String user = "test";
		String password = "test";
		Connection con = null;
		try {
			Class.forName(className);
			con = DriverManager.getConnection(url, user, password);
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		}
		return con;
	}
}

CallableStatement がストアドプロシージャを実行するためのインターフェイスになります。
入力パラメータは setXXX メソッドで、出力パラメータは registerOutParameter メソッドで設定します。

・CallableStatement (Java Platform SE 8 )
http://docs.oracle.com/javase/8/docs/api/java/sql/CallableStatement.html

型の指定は Types クラスで行なう感じで。select_t1_cursor は出力パラメータが Oracle の REF CURSOR なので OracleTypes の CURSOR を指定しています ( *1 )。

・Types (Java Platform SE 8 )
http://docs.oracle.com/javase/8/docs/api/java/sql/Types.html

・OracleTypes (Oracle ® Database JDBC API Reference)
http://docs.oracle.com/cd/E11882_01/appdev.112/e13995/oracle/jdbc/OracleTypes.html

( *1 ) Types クラスにも REF_CURSOR がありますが、こいつだと上手く動きませんでした。以下のドキュメントにも REF CURSOR のコールは OracleTypes.CURSOR 指定しろ、とあるので、まぁ、Oracle の固有の型を使う場合はそういうことなのでしょう。

・アプリケーションの拡張: 拡張JDBC機能
- メソッドからのREF CURSORのコール
http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/appdev.111/E05692-02/addfunc.htm#4666


以上です。

[ 環境情報 ]
Windows 7 SP1
Java SE 8 Update 25
Oracle JDBC Driver 12.1.0.2 ( ojdbc7.jar ) ( *2 )

CentOS 5.5
Oracle Database 11g Release 2 ( 11.2.0.1.0 )

( *2 ) 「Which version of JDBC drivers support which version of Oracle database?」の記述的に JDBC 12.1.0.x は Database 11.2.0.x をサポートしているようで。

Oracle JDBC Frequently Asked Questions
http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html