PL/SQL⇔JDBCメモ

新規に他システムと連携することになった。
そいで関数と引数しかもらえなかったので「(PL/SQL触ったことねぇから)テストユーザくれ」って再三お願いした。
結局リリース当日にやっともらえて本番ぶっつけだった。
そして案の定シクる、と。
ググっても欲しい情報が引っかからなかったからサンプルコード書いてメモっとく。

// 関数: ITEM.IS_AVALABLE
// 引数: 商品ID VARCHAR
// 戻値: 商品が注文可能かのフラグNUMBER
// 0:注文不可 1:注文可
String plsql = "{? = call ITEM.IS_AVALABLE(?)}"

// 商品コード
String itemCode = "C052-552";

// コネクション取得
Connection conn = ConnectionManager.getConnection();

// ステートメント取得
CallableStatement stmt = conn.prepareCall(plsql);

// 一個目の?(戻り値)
stmt.registerOutParameter(1, Types.INTEGER);

// 二個目の?(引数)
stmt.setString(2, itemCode);

// クエリ実行
stmt.executeQuery();

// 結果取得
int resultCode = stmt.getInt(1);


●以下、失敗談
:ぶっつけ本番で動作確認とか…
:とりあえず、れっつら起動
:何?FROM句が無いって、「SELECT 1」だけじゃダメなの?
Oracleでは接続検証用のSQLするなら「SELECT 1 FROM DUAL」ってしなきゃいけないのかー
:DUALてそういやEXISTSの例文で見たな。。。誰でも参照できる空テーブルだっけ(?)
:「パラメータの型が競合します。」 てぇ…んんん?

CallableStatement stmt = conn.prepareCall(plsql);
stmt.registerOutParameter(1, Types.INTEGER);
stmt.setString(1, itemCode);

:ああ、出力と入力で別のインデックスかと思ってた。戻り値は?の数以降とか?

stmt.registerOutParameter(1, Types.INTEGER);
↓
stmt.registerOutParameter(2, Types.INTEGER);

:「列索引が無効です。」ふんぎゃぁ

String plsql = "{call ITEM.IS_AVALABLE(?)}"

:関数だから、戻り値をセットする場所つくってあげればおk?

String plsql = "{call ITEM.IS_AVALABLE(?)}"
↓
String plsql = "{? = call ITEM.IS_AVALABLE(?)}"
stmt.registerOutParameter(1, Types.INTEGER);
stmt.setString(2, itemCode);

:キター!!!あとは戻り値をゲトーして、と。

ResultSet rset = stmt.executeQuery();
while (rset.next()) {
  int resultCode = rset.getInt(1);
  break;
}

:FETCHはいらない…だと…?ああ、複数行帰ってくるわけじゃないしね。

stmt.executeQuery();
int resultCode = stmt.getInt(1);

:やっと動いた…