| 目次 | 前の項目 | 次の項目 | JDBCTM ガイド: 使用の開始 |
CallableStatement オブジェクトは、すべての DBMS について標準的な方法でストアドプロシージャを呼び出す方法を提供します。ストアドプロシージャは、データベースに格納され、ストアドプロシージャへの呼び出しは、CallableStatement
オブジェクトが保持します。この呼び出しは、結果パラメータを伴う形式と、伴わない形式の 2 つの形式のどちらかを取るエスケープ構文で書かれます。エスケープ構文についての詳細は、4 項の「文」を参照してください。結果パラメータは OUT パラメータの一種で、ストアドプロシージャの戻り値です。どちらの形式も、入力 (IN パラメータ)、出力 (OUT パラメータ)、またはその両方 (INOUT パラメータ) として使用する変数を持つことができます。疑問符はパラメータのプレースホルダとして使用できます。
JDBC のストアドプロシージャの構文を以下に示します。角括弧は、それに囲まれた部分がオプションであることを示します。これらのかっこは、それ自体構文の一部ではありません。
{call procedure_name[(?, ?, ...)]}
以下は、結果パラメータを返すプロシージャの構文です。
{? = call procedure_name[(?, ?, ...)]}
パラメータが付かないストアドプロシージャの構文は、以下のようになります。
{call procedure_name}
通常、CallableStatement オブジェクトの作成者は、使用されている DBMS がストアドプロシージャをサポートしていること、およびそれらのプロシージャが何かということを知っています。しかし、確認が必要な場合は、さまざまな DatabaseMetaData メソッドがこのような情報を提供します。たとえば、メソッド supportsStoredProcedures は、DBMS がストアドプロシージャ呼び出しをサポートする場合、true を返し、メソッド getProcedures は、使用可能なストアドプロシージャの説明を返します。
CallableStatement は、SQL 文一般を処理する Statement のメソッドを継承し、また IN パラメータを処理する PreparedStatement のメソッドを継承します。CallableStatement に定義されているすべてのメソッドは、OUT パラメータまたは INOUT パラメータの OUT 部分の処理 (OUT パラメータの JDBC の型の登録、それらの値の取り出し、または戻り値が JDBC NULL であったかどうかの確認) を行います。
CallableStatement オブジェクトは、Connection メソッドの prepareCall によって作成されます。以下の例では、2 つの引数を持ち、結果パラメータを持たないストアドプロシージャ getTestData への呼び出しが入っている CallableStatement のインスタンスを生成します。
CallableStatement cstmt = con.prepareCall(
"{call getTestData(?, ?)}");
プレースホルダ ? が IN、OUT、INOUT パラメータのどれになるかは、ストアドプロシージャ getTestDataに依存します。CallableStatement オブジェクトへの引き渡しは、PreparedStatement から継承された setXXX メソッドを使用して行われます。渡される値の型は、どの setXXX (float の値を渡すためには setFloat など) を使用するかによって決定されます。
ストアドプロシージャが OUT パラメータを返す場合、各 OUT パラメータの JDBC の型は CallableStatement を使用する前に登録する必要があります。DBMS の中には JDBC の型を要求するものがあるのでこれが必要です。JDBC の型の登録は、メソッド registerOutParameter によって行います。文が実行されると、CallableStatement の
getXXX メソッドがパラメータ値を取り出します。使用すべき正しい getXXX メソッドは、そのパラメータに登録された JDBC の型に対応する Java の型です (JDBC の型から Java の型への標準マッピングが、項 8.6.1 の一覧に示されている)。いいかえると、registerOutParameter は、(それがデータベースが返す JDBC の型に一致するように) JDBC の型を使用し、getXXX がそれを Java の型にキャストします。
例を挙げて説明すると、以下のコードは OUT パラメータを登録し、cstmtが呼び出すストアドプロシージャを実行してから、OUT パラメータに返された値を取り出します。メソッド getByte は、最初の OUT パラメータから Java バイトを取り出し、getBigDecimal は、2 番目の OUT パラメータから BigDecimal オブジェクト (小数点以下第 3 位まで) を取り出します。
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);
registerOutParameter を呼び出す以外に、 (PreparedStatementから継承された) 適切な setXXXを呼び出す必要があります。setXXX メソッドは、パラメータの値を入力パラメータに設定し、メソッド registerOutParameter がその JDBC の型を出力パラメータとして登録します。setXXX メソッドは、ドライバがそれをデータベースに送信する前に JDBC の値に変換した Java の値を提供します。
この IN の値の JDBC の型と、メソッド registerOutParameter に供給される JDBC の型は同一でなければなりません。そして、出力値を取り出すために、対応する getXXX メソッドが使用されます。たとえば、その Java タイプが byte であるようなパラメータは、メソッド setByte を使用して入力値を指定し、JDBC の型として TINYINT を registerOutParameter に供給し、getByte を使用して出力値を取り出す必要があります (さらに詳細な情報と型のマッピングの一覧については、8 項の「SQL とJava の型のマッピング」を参照)。
以下の例は、ストアドプロシージャ reviseTotal があり、そのパラメータが INOUT パラメータだけである場合を想定しています。メソッド setByte はこのパラメータを 25 に設定し、ドライバはこれを JDBC の TINYINT としてデータベースに送信します。次の registerOutParameter は、このパラメータを JDBC の TINYINT として登録します。ストアドプロシージャが実行されると、新しい JDBC TINYINT の値が返され、メソッド getByte がこの新しい値を Java の 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);
CallableStatement.getXXX メソッドを使用して OUT パラメータを取り出す前に、CallableStatement オブジェクトの実行によって生成されたすべての結果を取り出すことをお勧めします。
CallableStatement オブジェクトが (メソッド execute を使用して) 複数の ResultSet オブジェクトを返す場合、OUT パラメータを取り出す前に、すべての結果セットにアクセスする必要があります。この場合、すべての結果に確実にアクセスするように、結果がなくなるまで Statement のメソッド getResultSet、getUpdateCount、および getMoreResults を呼び出す必要があります。
これが終わったら、CallableStatement.getXXX メソッドを使用して、OUT パラメータの値を取り出すことができます。
JDBC NULL である場合があります。JDBC NULL 値は、getXXX メソッドが返す値が getXXX メソッドの型によって null、0、false のどれかになるように変換されます。ResultSet オブジェクトについては、0 または false の値が元々 JDBC NULL であったかどうかを知る方法は、メソッド wasNull を使用して確認する方法だけです。この場合、getXXX メソッドが読み取った最後の値が JDBC NULL の場合は true が返され、そうでない場合は false が返されます。詳細については、5 項の「ResultSet」を参照してください。