web-dev-qa-db-ja.com

JDBCバッチ挿入例外処理

プログラムが実行されるたびに、JDBCバッチ挿入(約1000行を一度に挿入)を実行しています。しかし、一部のレコードによってスローされた例外を適切に処理できません。

データが無効であるか、値のサイズが列のサイズを超えているため、1000レコードのうち100番目のレコードが例外をスローするとします。例外が発生すると、残りのレコードは挿入されず、プログラムはその間に失敗します。

私が欲しいのは、100番目のレコードが例外をスローしている場合でも、残りの挿入は、プログラムが終了する前に通常どおり発生するはずです。

これを達成する方法を理解できません。提案してください。

編集:

これは、アプリでバッチ挿入に使用しているサンプルコードです。結果セットのレコード数が約1000であると想定します。

PreparedStatement ps = null;
while(rs.next()){
  //Retrieve the value and set it to a Prepared statement

  String name = rs.getString("Name");
  int age = rs.getInt("Age");
  ps.setInt(1, age);
  ps.setString(2, name);

  //Finally invoke addBatch
  ps.addBatch();
}

//Finally call the executeBatch method
ps.executeBatch();

100番目のレコードが例外をスローしている場合、100番目から1000番目までのレコードからのみプロセスをトリガーします。例外をスローしたレコードからプロセスを再開できるようにする方法はありますか以降再び最後まで?これを達成する方法は?

21
user182944

SQLステートメントのバッチを実行しているとおっしゃっていますので、executeBatchを使用していると思います。ステートメントのバッチをexecuteBatch実行すると、一部のステートメントが成功し、一部のステートメントが失敗する場合があります。 1つのステートメントが失敗しても、JDBCドライバーが成功したステートメントをロールバックするわけではありません。 JDBCドライバーは、1つのステートメントが失敗した場合にバッチ内のすべてのステートメントの実行を試みるか、ステートメントが失敗するとバッチ内のステートメントの実行を停止するかを選択する場合があります(使用しているドライバーがステートメントの実行を停止するように選択しているようです)障害が発生するとすぐに)。

バッチ内の1つのステートメントが失敗すると、BatchUpdateExceptionを取得する必要があります。例外ハンドラで、getUpdateCountsを呼び出す必要があります。これにより、ステートメントが更新された行数、ステートメントは成功したが行カウントが利用できなかったことを示すStatement.SUCCESS_NO_INFO、またはStatement.EXECUTE_FAILEDのいずれかを示すintの配列が得られますステートメントは失敗しました。最初の99個のステートメントが成功し、100番目のステートメントがエラーを生成し、残りのステートメントが実行されない場合、最初の99個の要素が成功を示し、100番目の要素がStatement.EXECUTE_FAILEDを示す100要素の配列が返されます。次に、コードは、実行されなかったステートメント(この場合はステートメント101〜1000)を再試行する必要があります。

27
Justin Cave

コードをまったく見ないで、私ができる最善のアドバイスは、挿入を行うコードをtry/catchブロックで囲むことです。また、おそらく挿入ごとに(トランザクション接続を想定して)挿入をコミットする必要があります。これにより、処理が少し遅くなりますが、プログラムは続行できます。

よりクリーンなアプローチは、挿入する前にレコードを事前検証することです。一度に約1000件のレコードしか話していなければ、これは処理負荷の大部分にはなりません。

0
Mike Clark