Обработка исключений пакетной вставки JDBC

Я выполняю пакетную вставку JDBC (вставляя по 1000 строк примерно за раз) каждый раз, когда выполняется моя программа. Но я не могу обработать исключение, созданное некоторыми из записей.

Предположим, 100-я запись из 1000 записей выбрасывает исключение из-за недопустимых данных или размера некоторого значения, превышающего размер столбца. После возникновения исключения оставшиеся записи не встают и программа прерывается между ними.

Я хочу, даже если 100-я запись бросает исключение, остальные вставки должны происходить, как обычно, до окончания моей программы.

Я не могу понять, как этого добиться. Пожалуйста, предложите.

EDIT:

Вот пример кода, который я использую в своем приложении для пакетной вставки. Предположим, что результирующий набор имеет около 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-й записи. Есть ли способ сделать это, чтобы я мог перезапустить процесс из записи, которая до конца закрывала исключение вперед? Как достичь этого?

Ответы

Ответ 1

Вы заявляете, что выполняете партии операторов SQL, поэтому я предполагаю, что вы используете executeBatch. Когда вы executeBatch пакет операторов, некоторые из операторов могут преуспеть, а некоторые из инструкций могут завершиться неудачно. Если один из операторов не работает, это не означает, что драйвер JDBC откатывает завершающие утверждения. Драйвер JDBC может попытаться выполнить все инструкции в пакете, если один из них не работает, или может прекратить выполнение операторов в пакете после выключения оператора (похоже, что драйвер, который вы используете, предпочитает останавливать выполнение операторов как как только произойдет сбой).

Когда один оператор в пакете терпит неудачу, вы должны получить BatchUpdateException. В обработчике исключений вам необходимо вызвать getUpdateCounts. Это даст вам массив int, в котором указывается, сколько строк обновляется, а Statement.SUCCESS_NO_INFO указывает на то, что оператор преуспел, но количество строк не было доступно, или Statement.EXECUTE_FAILED, указывающее на то, что инструкция не выполнена. Если первые 99 операторов преуспевают, 100-й оператор генерирует ошибку, а остальные операторы не выполняются, вы должны вернуть 100-элементный массив, в котором первые 99 элементов указывают на успех, а 100-й элемент указывает Statement.EXECUTE_FAILED. Затем вашему коду нужно будет повторить те инструкции, которые не были выполнены (в данном случае, заявления 101-1000).

Ответ 2

Не видя никакого кода, лучший совет, который я могу дать, - это обернуть блок try/catch вокруг вашего кода, который вставляет. Вероятно, вам также понадобится зафиксировать свои вставки (при условии транзакционного соединения) в каждой вставке. Это приведет к немного более медленной обработке, но позволит вашей программе продолжить.

Я думаю, что более чистый подход состоял бы в том, чтобы попытаться предварительно проверить записи перед вставкой. Это не должно быть связано с большей нагрузкой на обработку, если мы говорим только о 1000 записей за раз.