| 目次 | 前の項目 | 次の項目 | JDBCTM ガイド: 使用の開始 |
PreparedStatement インタフェースは、Statement から継承しますが、以下の 2 つの点で異なります。
PreparedStatement のインスタンスには、すでにコンパイル済みの SQL 文が入っています。文が「prepared」(準備済み) と呼ばれるのはこのためです。
PreparedStatement に入っている SQL 文には、1 つ以上の IN パラメータを付けることができます。IN パラメータは、SQL 文が作成されたときにはその値が指定されていないパラメータです。その代わり、文には IN パラメータのプレースホルダとして疑問符 ( ? ) が付いています。それぞれの疑問符の値は、文を実行する前に適切な setXXX メソッドによって供給される必要があります。
PreparedStatement オブジェクトはすでにコンパイル済みなので、Statement オブジェクトより高速に実行することができます。したがって、何度も実行される SQL 文は、 PreparedStatement オブジェクトとして作成して効率を高めることがよくあります。
PreparedStatement は Statement のサブクラスであるため、Statement のすべての機能を継承します。さらに、IN パラメータのプレースホルダの代わりにデータベースに送信する値を設定するのに必要なすべてのメソッドを追加します。また、3 つのメソッドの execute、executeQuery、および executeUpdate は、引数を取らないように変更されています。この 3 つのメソッドの Statement 形式 (SQL 文のパラメータを取る形式) は、
PreparedStatement オブジェクトに対しては絶対に使用してはなりません。
con は Connection オブジェクト) は、IN パラメータのための 2 つのプレースホルダがある SQL 文の PreparedStatement オブジェクトを作成します。
PreparedStatement pstmt = con.prepareStatement(
"UPDATE table4 SET m = ? WHERE x = ?");
これで、オブジェクト pstmt には、"UPDATE table4 SET m = ? WHERE x = ?" という文が入り、DBMS に送信されて実行準備済みの状態になります。
PreparedStatement オブジェクトが実行される前に、各 ? パラメータの値を設定する必要があります。これは、setXXX メソッドを呼び出すことによって行います。XXX は、パラメータの適切な型です。たとえば、パラメータが long という Java の型を持つ場合、使用するメソッドは setLong です。setXXX メソッドの最初の引数は、設定するパラメータの順序で、2 番目の引数は、パラメータに設定する値です。たとえば、以下のコードは、最初のパラメータを 123456789 に、2 番目のパラメータを 100000000 に設定します。
pstmt.setLong(1, 123456789);
pstmt.setLong(2, 100000000);
その文にパラメータの値が設定されると、そのパラメータは、メソッド clearParameters への呼び出しによってクリアされるまで、その文が実行されるたびに何度でも使用されます。
接続のためのデフォルトモード (自動コミット有効) では、接続が確立されると各文が自動的にコミットされたり、ロールバックされたりします。
PreparedStatement オブジェクトは、コミット後、基盤のデータベースとドライバがそれを開いたままにしていれば、同じオブジェクトを複数回実行することができます。ただし、これ以外の場合は、Statement オブジェクトの代わりに PreparedStatement オブジェクトを使用してパフォーマンスの向上を試みることには、まったく意味がありません。
以下のコードでは、上で作成した pstmt、PreparedStatement オブジェクトを使用して、2 つのパラメータのプレースホルダの値の設定と pstmt を 10 回実行する方法を説明します。前述のように、これが機能するためには、データベースが pstmt を閉じないようにする必要があります。この例では、最初のパラメータに "Hi" が設定され、定数のままになります。2 番目のパラメータには、0 で始まり、for ループを通るたびに異なる値が設定されて、最後は 9 で終ります。
pstmt.setString(1, "Hi");
for (int i = 0; i < 10; i++) {
pstmt.setInt(2, i);
int rowCount = pstmt.executeUpdate();
}
setXXX メソッドの XXX は Java の型です。ドライバが (この JDBC ガイドの 8.6.2 項、「JDBC の型にマッピングされる Java の型」 の一覧に指定されたマッピングに従って) Java の型を対応する SQL の型にマッピングし、その SQL タイプをデータベースに送信するので、これは暗黙的には SQL の型です。たとえば、以下の部分的なコードは、PreparedStatement オブジェクト pstmt の 2 番目のパラメータを short という Java の型で 44 に設定します。
pstmt.setShort(2, 44);ドライバは 44 を、 Java の
short からの標準マッピングである JDBC の SMALLINT としてデータベースに送信します。
Java 型の各 IN パラメータが、データベースが期待する JDBC のデータ型と互換性のある JDBC の型に確実にマッピングするかは、プログラマの責任です。データベースが JDBC
SMALLINT を期待している場合を想定してください。メソッド setByte が使用される場合、ドライバは、JDBC の TINYINT をデータベースに送信します。多くのデータベースでは、1 つの関連する型から他の型に変換すること、また一般に TINYINT は、SMALLINT が使用されているところではどこでも使用できることから、これは通常は動作します。しかし、アプリケーションができるだけ多くのデータベースで機能するためには、データベースが期待する正確な JDBC の型に対応する Java の型を使用するのがもっともよい方法です。期待される JDBC の型が SMALLINT の場合、setByte の代わりに setShort を使用することにより、アプリケーションの移植性を向上させることができます。
setObject を使用して、入力パラメータを特定の JDBC の型に明示的に変換できます。このメソッドは、3 番目の引数を取って、対象の JDBC の型を指定できます。ドライバは、Java の Object を指定した JDBC の型に変換してからデータベースに送信します。
JDBC の型が指定されていない場合、ドライバは (8.6.4 項の一覧を使用して)、単純に Java の Object をそのデフォルトの SQL の型にマッピングして、データベースに送信します。これは、通常の setXXX の処理と似ています。どの場合も、ドライバが Java の型を適切な JDBC の型に変換してから、データベースに送信します。相違点としては、setXXX メソッドが、Java の型から JDBC の型への標準のマッピングを使用するのに対し
(9.5.2 項の一覧参照)、setObject メソッドは、Java の Object 型から JDBC の型へのマッピングを使用します (8.6.4 項の一覧参照)。
メソッド setObject はあらゆる Java オブジェクトを許容する能力を持つため、アプリケーションを汎用化して、パラメータ入力を実行時に受け取ることができます。その場合、アプリケーションのコンパイル時には入力の型は不明です。setObject を使用することにより、アプリケーションは任意の Java のオブジェクト型を入力として受け取り、それをデータベースが期待する JDBC の型に変換することができます。8.6.5 項の一覧に、setObject が実行できるすべての変換を示します。
setNull メソッドにより、プログラマは、JDBC の NULL 値を IN パラメータとしてデータベースに送信することができます。ただし、JDBC 型のパラメータを指定することが必要になることに注意してください。
Java の null 値が setXXX メソッドに渡された場合、JDBC の NULL もデータベースに送信することができます (Java オブジェクトを引数として取る場合)。ただし、メソッド
setObject が null 値を取れるのは、 JDBC の型が指定されている場合に限ります。
setBytes および setString は、無限の量のデータを送信できます。ただし、場合によっては、プログラマが大量のデータを小さな塊で渡したいと考えることがあります。これは、IN パラメータを Java 入力ストリームに設定することによって達成できます。文の実行時に、JDBC ドライバがこの入力ストリームを繰り返し呼び出し、その内容を読みとって、それを実際のパラメータデータとして伝送します。
JDBC には、IN パラメータを入力ストリームに設定するための方法が 3 通りあります。これらは、未解釈のバイトが入ったストリームのための
setBinaryStream、ASCII 文字の入ったストリームのための setAsciiStream、および Unicode 文字の入ったストリームのための setUnicodeStream です。これらのメソッドは、ストリーム全体の長さを指定する必要があるので、他の setXXX メソッドより引数を 1 つ多く取ります。データベースによっては、データ送信の前に全転送サイズを知る必要があるので、この引数が必要になります。
以下のコードは、ストリームを使用し、ファイルの内容を IN パラメータとして送信する方法を示します。
java.io.File file = new java.io.File("/tmp/data");
int fileLength = file.length();
java.io.InputStream fin = new java.io.FileInputStream(file);
java.sql.PreparedStatement pstmt = con.prepareStatement(
"UPDATE Table5 SET stuff = ? WHERE index = 4");
pstmt.setBinaryStream (1, fin, fileLength);
pstmt.executeUpdate();
文が実行されると、入力ストリーム fin が繰り返し呼び出され、そのデータを配信します。