Обработка исключений пакетной вставки 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 записей за раз.