17.5.2 バッチ更新
JDBC2.1 コアAPIでは,Statementクラス及びPreparedStatementクラスにバッチ更新機能が追加されました。バッチ更新機能によって,複数のSQL,又は複数のパラメタ値を登録し,一括して実行できるようになります。
バッチ更新を実行する場合,HiRDBの配列を使用した機能が使用できます。
配列を使用した機能は,HiRDBに対して大量のデータを高速に更新したい場合に有効です。なお,配列を使用した機能については,「配列を使用した機能」を参照してください。
- 〈この項の構成〉
(1) Statementクラスでのバッチ更新
Statementクラスでのバッチ更新の留意点を次に示します。
-
複数の更新系SQLを,addBatchメソッドで登録します。
-
登録した更新系SQLを,executeBatchメソッドで一括して実行します。
-
一括実行の結果として,それぞれの更新系SQLで更新された行数の配列を返却します。
-
一括実行の途中でエラーが発生した場合,BatchUpdateExceptionを投入します。
-
登録したSQL中に検索系SQLがある場合,executeBatchメソッド呼び出し時にBatchUpdateExceptionを投入します。
なお,JDBCドライバでは,複数のSQLを一括実行できないため,登録されたSQLを逐次実行することになります。
(2) PreparedStatementクラスでのバッチ更新
PreparedStatementクラスでのバッチ更新の留意点を次に示します。
-
PreparedStatementインスタンス生成時に指定した更新系SQLに対する?パラメタを,通常の手順(setXXXメソッド)で設定します。
-
addBatchメソッドで?パラメタのセットを登録します。
-
登録した複数セットの?パラメタを,executeBatchメソッドで一括して実行します。
-
一括実行の結果として,それぞれの?パラメタのセットで更新した行数の配列を返却します。
-
一括実行の途中でエラーが発生した場合,BatchUpdateExceptionを投入します。
-
PreparedStatementインスタンス生成時に指定したSQLが検索系SQLの場合,executeBatchメソッド呼び出し時にBatchUpdateExceptionを投入します。
なお,JDBCドライバでは,次の場合に逐次実行します。
-
パラメタとSQL文のaddBatchの混在時でのバッチ更新
-
HiRDBのBINARY型に対する?パラメタを含むSQL文でのバッチ更新(BINARY型の?パラメタに設定するデータの長さが32,001バイト以上の場合)
-
HiRDBのBLOB型に対する?パラメタを含むSQL文でのバッチ更新
- <注意事項>
-
2件目以降のaddBatchで,setXXXメソッドで指定するパラメタ数が不足していた場合,前回セットした値が引き継がれるため注意が必要です。
INTEGER型列が2列(列1,列2)ある場合の例を次に示します。
- [指定例]
prepstmt.setInt(1,100); prepstmt.setInt(2,100); prepstmt.addBatch(); prepstmt.setInt(1,200); prepstmt.addBatch(); prepstmt.executeBatch();
- [説明]
-
-
1件目のaddBatchで設定される値は,列1=100,列2=100となります。
1件目のaddBatchでパラメタ数が不足している場合は,エラーが発生します。
-
2件目のaddBatchで設定される値は,列1=200,列2=100となります。
2件目のaddBatchで,列2の情報が更新されていないため,1件目のaddBatchの情報が引き継がれます。
-
(3) CallableStatementクラスでのバッチ更新
CallableStatementクラスでのバッチ更新の留意点を次に示します。
-
CallableStatementインスタンス生成時に指定したJavaストアドルーチンに対する入力パラメタを,通常の手順(setXXXメソッド)で設定します。
-
addBatchメソッドで入力パラメタのセットを登録します。
-
登録した複数セットの入力パラメタを,executeBatchメソッドで一括して実行します。
-
一括実行の結果として,それぞれの入力パラメタのセットで実行したJavaストアドルーチンの返却値(更新行数)の配列を返却します。
-
一括実行の途中でエラーが発生した場合,BatchUpdateExceptionを投入します。
-
CallableStatementインスタンス生成時に指定したJavaストアドルーチンが,更新行数を返却するルーチンでない場合,executeBatchメソッド呼び出し時にBatchUpdateExceptionを投入します。
-
CallableStatementインスタンス生成時に指定したJavaストアドルーチンが,出力パラメタ及び入出力パラメタを持つ場合,addBatchメソッド呼び出し時にBatchUpdateExceptionを投入します。
なお,JDBCドライバでは,複数行のストアドプロシジャの?パラメタを一括実行できないため,複数行のストアドプロシジャの?パラメタを逐次実行することになります。
- 注意事項:
-
結果セット(ResultSet)を返すストアドプロシジャは,バッチ更新ではストアドプロシジャを実行するまで結果セットを返すかどうか分からないため,ストアドプロシジャ内で更新をしている場合,更新が反映されることがあるので注意してください。例えば,更新後にその結果を検索し取得するストアドプロシジャを,バッチ更新で実行すると,BatchUpdateExceptionが発生するが,更新は反映されてしまうことがあります。
(4) 注意事項
(a) HiRDBサーバによる暗黙的コミット
SQL文のバッチ更新機能を使用する場合,addBatchしたSQL文に次のSQL文が含まれるとき,そのSQL文を実行した時点でHiRDBサーバが暗黙的にコミットするため,注意が必要です。
-
PURGE TABLE文
-
クライアント環境定義PDCMMTBFDDLにYESを設定した状態での定義系SQL
(b) パラメタとSQL文のaddBatchの混在時でのバッチ更新機能
パラメタとSQL文のaddBatchとの混在時は,一括更新をしないで逐次実行します。例を次に示します。
PreparedStatement pstmt = con.prepareStatement("UPDATE T1 SET C1=? WHERE C2=?"); pstmt.setInt(1, 1); pstmt.setInt(2, 1); pstmt.addBatch(); pstmt.setInt(1, 2); pstmt.setInt(2, 2); pstmt.addBatch(); pstmt.addBatch("INSERT INTO T2 VALUES(1,2,3)"); pstmt.setInt(1, 3); pstmt.setInt(2, 4); pstmt.addBatch(); pstmt.setInt(1, 4); pstmt.setInt(2, 4); pstmt.addBatch(); pstmt.executeBatch();
このUAPを実行すると,パラメタとSQL文のaddBatchが混在しているため,各addBatch単位でのSQL実行となります。そのため,次のUAPを実行した場合と同じ結果となります。
PreparedStatement pstmt = con.prepareStatement("UPDATE T1 SET C1=? WHERE C2=?"); pstmt.setInt(1, 1); pstmt.setInt(2, 1); pstmt.executeUpdate(); pstmt.setInt(1, 2); pstmt.setInt(2, 2); pstmt.executeUpdate(); pstmt.executeUpdate("INSERT INTO T2 VALUES(1,2,3)"); pstmt.setInt(1, 3); pstmt.setInt(2, 4); pstmt.executeUpdate(); pstmt.setInt(1, 4); pstmt.setInt(2, 4); pstmt.executeUpdate();
なお,パラメタとSQL文のaddBatchとが混在するバッチ更新機能を使用する場合,Connectionクラスの自動コミットモードを無効にすることを推奨します。
(c) HiRDBのBINARY型に対する?パラメタを含むSQL文でのバッチ更新
HiRDBのBINARY型に対する?パラメタを含むSQL文でバッチ更新をする場合,次の条件に該当するとき,一括更新をしないで逐次実行します。
-
?パラメタに対してsetXXXメソッドで設定するデータ長が32,001バイト以上である(setStringメソッドなどで文字データを指定している場合は,HiRDBに渡すデータにエンコードした後のデータ長が32,001バイト以上である)。
(d) HiRDBのBLOB型に対する?パラメタを含むSQL文でのバッチ更新
HiRDBのBLOB型に対する?パラメタを含むSQL文でバッチ更新をする場合,一括更新をしないで逐次実行します。
(e) addBatchメソッドによって多数のパラメタを登録する場合
JDBCドライバは,addBatchメソッドで登録したすべてのパラメタを,executeBatchメソッドを実行するまでドライバ内に蓄積します。そのため,多数のパラメタを登録する際は,メモリ使用量に注意してください。
また,HiRDBの配列を使用した機能でバッチ更新をする場合,HiRDBサーバに対してJDBCドライバが要求できる実行回数は最大で30,000回です。30,001個以上のパラメタを登録している場合,1回のバッチ更新で用いるパラメタを30,000個単位に分割し,HiRDBサーバに対してSQLの実行を要求します。この場合も,JDBCドライバ内のメモリを消費するため,バッチ更新による性能向上効果が下がるおそれがあります。そのため,30,001回以上のSQL実行が必要な場合は,30,000回以下の単位でexecuteBatchメソッドを実行することを推奨します。
(f) 例外BatchUpdateExceptionで通知する更新カウント
バッチ更新実行時に発生する例外BatchUpdateExceptionの,getUpdateCountsメソッドの戻り値で通知する更新カウント(int型の配列)の内容を次の表に示します。
バッチ更新の実行形態 |
BATCHEXCEPTION_BEHAVIOR※1の設定値 |
|
---|---|---|
TRUE |
FALSE |
|
配列機能を利用した一括実行 |
要素数0の配列 |
要素数nの配列 n:何回目のaddBatchで登録したパラメタでエラーになったかを示します。 エラーが発生するとロールバックされるため,すべての配列要素にはStatement.EXECUTE_FAILEDが設定されます。 |
JDBCドライバによる逐次実行 |
要素数が実行したSQL数の配列 各配列要素には更新行数※2を設定 |
要素数nの配列 n:何回目のaddBatchで登録したパラメタ又はSQLでエラーになったかを示します。 配列要素には次の値が設定されます。 要素0〜n-2:更新行数※2 要素n-1:Statement.EXECUTE_FAILED |
- 注※1
-
次のどれかで指定します。
-
HiRDB接続時のユーザプロパティHiRDB_for_Java_BATCHEXCEPTION_BEHAVIOR
-
URLのBATCHEXCEPTION_BEHAVIOR
-
DataSource系インタフェースのsetBatchExceptionBehaviorメソッド
なお,接続先がバージョン08-01以前のHiRDBの場合,"TRUE"が指定されたものとして動作します。
-
- 注※2
-
CallableStatementクラスのexecuteBatchメソッドでCALL文を実行した場合,Statement.SUCCESS_NO_INFOを設定します。
更新カウントの例を次に示します。
≪配列機能を利用した一括実行のプログラム例≫
PreparedStatement pstmt = con.prepareStatement("INSERT INTO T1 VALUES(?,?)"); pstmt.setInt(1, 1); pstmt.setString(2,"aaaa"); pstmt.addBatch(); pstmt.setInt(1, 2); pstmt.setString(2,"bbbbbbbb"); pstmt.addBatch();.......................................[A] pstmt.setInt(1, 3); pstmt.setString(2,"cccc"); pstmt.addBatch(); pstmt.executeBatch();
≪JDBCドライバによる逐次実行のプログラム例≫
Statement stmt = con.createStatement(); stmt.addBatch("INSERT INTO T1 VALUES(1,'aaaa')"); stmt.addBatch("INSERT INTO T1 VALUES(2,'bbbbbbbb')");...[A] stmt.addBatch("INSERT INTO T1 VALUES(3,'cccc')"); stmt.executeBatch();
プログラム例を実行し,[A]で登録したパラメタ,又はSQLの処理でエラーになった場合,getUpdateCountsメソッドで返却する更新カウントの内容を次に示します。
バッチ更新の実行形態 |
BATCHEXCEPTION_BEHAVIORの設定値 |
|
---|---|---|
TRUE |
FALSE |
|
配列機能を利用した一括実行 |
要素数0のint型の配列 |
要素数2のint型の配列 要素0の値:Statement.EXECUTE_FAILED 要素1の値:Statement.EXECUTE_FAILED |
JDBCドライバによる逐次実行 |
要素数1のint型の配列 要素0の値:更新行数 |
要素数2のint型の配列 要素0の値:更新行数 要素1の値:Statement.EXECUTE_FAILED |