目次 | 前の項目 | 次の項目 | JDBCTM ガイド: 使用の開始 |
Statement
、PreparedStatement
、CallableStatement
の各オブジェクトが使用できます。
Statement
オブジェクトで、基盤となる DBMS に、異なる一連の更新コマンドを一括して (バッチとして) 送ることができます。次の例では、新入社員を架空の会社のデータベースに追加するために必要な一連の更新操作文を、1 つのバッチとして送っています。
この例では、// turn off autocommit con.setAutoCommit(false); Statement stmt = con.createStatement(); stmt.addBatch("INSERT INTO employees VALUES (1000, 'Joe Jones')"); stmt.addBatch("INSERT INTO departments VALUES (260, 'Shoe')"); stmt.addBatch("INSERT INTO emp_dept VALUES (1000, 260)"); // submit a batch of update commands for execution int[] updateCounts = stmt.executeBatch();
Statement.executeBatch()
が呼び出されたときに、ドライバがトランザクションをコミットしないように、自動コミットモードを無効にしています。自動コミットを無効にすることで、エラーが発生した場合や、バッチ中の一部のコマンドの処理に失敗した場合に、トランザクションをコミットするかどうかをアプリケーション側で制御できるようになります。このような理由から、常に、バッチ更新が終了した時点で自動コミットをオフにしておくべきです。executeBatch
のコミットの実装は、エラーが発生し、かつ自動コミットが true の場合に常に定義されます。
バッチ更新についての説明の普遍性を維持するため、バッチ内の各メンバのことを「要素」ということにします。これまでに見たように、バッチ内の要素は Statement
オブジェクトの使用時に実行される単純なコマンドです。ここでは、Statement
オブジェクトの使用方法をバッチ更新に限定していますが、以下の説明は PreparedStatment
および CallableStatement
オブジェクトにも当てはまります。
JDBC の新規 API には、Statement
オブジェクトには、まとめて送ることができるコマンドのリスト (つまりバッチ) を管理する機能があります。Statement
オブジェクトの作成時に、関連付けられたバッチは空 (つまり要素のない状態) です。呼び出し文のバッチに要素を追加するには、Statement.addBatch()
メソッドを使用します。作成したコマンドのバッチを送るのを中止したい場合は、Statement.clearBatch()
メソッド (上のコードにはない) を呼び出せばバッチを取り消すことができます。
Statement.executeBatch()
メソッドを呼び出すと、基盤となるデータソースに文のバッチが送られ、実行されます。バッチの各要素は、バッチに追加された順序で逐次 (少なくとも論理的な順序で) 実行されます。バッチ内の全要素の実行が成功すると、executeBatch()
はバッチ内の各要素に対し 1 つのエントリを含む整数配列を返します。配列内のエントリは、要素が処理された順序 (つまり、要素がバッチに追加された順序) に並べられます。配列内のエントリは、次の値を保持する場合があります。
executeBatch()
を呼び出すと、Statement
オブジェクトの現在の結果セットが開かれていれば、それが閉じられます。文が保持しているバッチ要素の内部リストは、executeBatch()
の実行が終了すると、空の状態にリセットされます。executeQuery
、executeUpdate
、または execute
メソッドの動作は、文のバッチが空ではない場合に定義および実装されます。
バッチファイル内のいずれかの要素の適正な実行に失敗するか、要素が結果セットを返そうとする場合、ExecuteBatch()
は BatchUpdateException
をスローします。バッチで実行できるのは、更新数だけを返す DLL コマンドと DML コマンドだけです。BatchUpdateException
がスローされると、BatchUpdateException.getUpdateCounts()
メソッドを呼び出して、バッチの実行結果を示す更新カウントの整数配列を取得できます。
バッチファイル内のある要素が実行された場合、JDBC ドライバは残りの要素の処理を続ける場合もあれば続けない場合もあります。ただし、特定の DBMS とともに使用する場合、JDBC ドライバは常に同じ機能を提供する必要があります。たとえば、あるバッチが失敗したあと、ドライバは別のバッチの処理を継続することはできません。
最初にバッチが失敗したあとでドライバが処理を停止する場合、BatchUpdateException.getUpdateCounts()
が返す配列に含まれるエントリの数は、バッチ内の要素数よりも常に少なくなります。要素は、バッチに追加された順番に実行されるため、配列に N 個の要素が含まれる場合、executeBatch()
の呼び出し時に、バッチ内の最初の N 個の要素の処理が成功することを意味します。
障害が発生してもドライバが処理を継続する場合、BatchUpdateException.getUpdateCounts()
が返す配列内の要素数 N は、常にバッチ内の要素数に等しくなります。BatchUpdateException
がスローされてもドライバが処理を継続する場合、次の付加的な配列値が返されます。
JDBC ベースのアプリケーションは、BatchUpdateException.getUpdateCounts()
が返す配列のサイズを調べることにより、失敗しても処理を継続する JDBC ドライバと、失敗後に処理を停止するドライバとを区別できます。処理を継続する JDBC ドライバは、バッチ内の各要素につき 1 つのエントリを含む配列を常に返します。失敗すると処理を停止する JDBC ドライバが返す配列内のエントリ数は、常にバッチ内の要素数よりも少なくなります。
PreparedStatement
の使用時にパラメータをとるコマンドおよび関連付けられたパラメータセットで構成されます。バッチ更新機能を PreparedStatement
と組み合わせて使用すると、1 つの PreparedStatement
オブジェクトに複数の入力パラメータ値のセットを関連付けることができます。これにより、パラメータ値のセットを、パラメータをとる形式の更新コマンドと一緒に、基盤となる DBMS エンジンにまとめて送ることができます。
下の例では、2 人の新入社員のレコードを 1 回のバッチ処理でデータベースに追加しています。各パラメータセット (社員ごとに 1 つ) の作成は PreparedStatement.setXXX()
で行い、現在のバッチへのパラメータセットの追加は PreparedStatement.addBatch()
メソッドで行なっています。
最後に、// turn off autocommit con.setAutoCommit(false); PreparedStatement stmt = con.prepareStatement( "INSERT INTO employees VALUES (?, ?)"); stmt.setInt(1, 2000); stmt.setString(2, "Kelly Kaufmann"); stmt.addBatch(); stmt.setInt(1, 3000); stmt.setString(2, "Bill Barnes"); stmt.addBatch(); // submit the batch for execution int[] updateCounts = stmt.executeBatch();
PreparedStatement.executeBatch()
で更新内容を DBMS に送っています。PreparedStatement.executeBatch()
を呼び出すと、文に関連付けられたバッチ要素のリストが消去されます。PreparedStatement.executeBatch()
が返す配列には、Statement
の場合と同様、バッチ内の各パラメータセットに対応する要素が含まれます。各要素には、更新カウントまたは「成功」を示す汎用のインジケータ (-2) のいずれかが含まれます。
PreparedStatement
オブジェクトのエラー処理は、Statement
オブジェクトのエラー処理と同様です。ドライバの中には、エラー発生後ただちに処理を停止するものもあれば、残りのバッチ処理を継続するものもあります。Statement
の場合、BatchUpdateException.getUpdateCounts()
が返す配列内の要素数を見ると、ドライバがエラー発生後にも処理を継続するかどうかがわかります。Statement
の場合、同一の値を 3 つ配列要素にとることができます。配列内のエントリの順序は、要素がバッチに追加された際の順序と同じです。
PreparedStatement
オブジェクトと同じように CallableStatement
オブジェクトも使用できます。複数の入力パラメータ値のセットを 1 つの CallableStatement に関連付け、まとめて DBMS に送ることができます。CallableStatement を使用したバッチ更新機能で呼び出されるストアドプロシージャは、更新数を返すものでなければなりません。 また、このようなストアドプロシージャでは、OUT パラメータと INOUT パラメータは使用できません。この規則に反した場合は、CallableStatement.executeBatch()
は例外をスローします。エラー処理は、PreparedStatement
の場合と同様です。
DatabaseMetaData.supportsBatchUpdates()
は true を返す必要があります。サポートしない場合は false を返す必要があります。 また、下位互換性を維持するため、失敗後に処理を停止する JDBC ドライバには、値 -2 (6.1 で説明) を返すことが求められているわけではありません。ただし、値 -2 を返すことは推奨されています。処理を継続する JDBC ドライバの場合、負の戻り値を両方ともサポートする必要があります。
注: 将来、JDBC API は 6.1 で説明した負の配列エントリ値用の記号定数を定義します。これらの値は、元の JDBC 2.0 API 仕様への付録として追加されています。