Как получить точный SQL-запрос, содержащий исключение при пакетной обработке

Я хочу выполнить следующее:

(перевод в БД ПРЕЗЕНТАЦИИ строки из выбранной строки БД ОБРАБОТКИ)

    PreparedStatement stmt;
    Statement st;
    Connection conn = ConnectionManager.getInstance().getConnection(ConnectionManager.PRESENTATION_DB);
    try {
        conn.setAutoCommit(false);
        stmt = conn.prepareStatement(
               "insert into customer (name,category,age) values (?,?,?)");  
                    stmt.clearParameters();
                    stmt.setString(1,"name2");
                    stmt.setString(2,"cat2");
                    stmt.setInt(3,25);
                    stmt.addBatch();
                    stmt.clearParameters();
                    stmt.setString(1,"name3");
                    stmt.setString(2,"cat3");
                    stmt.setInt(3,25);
                    stmt.addBatch();
                    stmt.clearParameters();
                    stmt.setString(1,"name4");
                    stmt.setString(2,"cat2");
                    stmt.setInt(3,25);
                    stmt.addBatch();
                    stmt.clearParameters();
                    stmt.setString(1,"name4");
                    stmt.setString(2,"cat2");
                    //stmt.setInt(3,25);

                    //this is parameter with false input
                    stmt.setString(3,"null"); 

                    stmt.addBatch();
                    stmt.clearParameters();
                    stmt.setString(1,"name5");
                    stmt.setString(2,"cat5");
                    stmt.setInt(3,25);
                    stmt.addBatch();
                    stmt.clearParameters();

        int [] updateCounts = stmt.executeBatch();
        conn.commit();
        conn.setAutoCommit(true);

                    stmt.close();
        conn.close();
    } 
    catch(BatchUpdateException b) {
                    System.err.println("-----BatchUpdateException-----");
                    System.err.println("SQLState:  " + b.getSQLState());
                    System.err.println("Message:  " + b.getMessage());
                    System.err.println("Vendor:  " + b.getErrorCode());
                    System.err.print("Update counts:  ");
                    int [] updateCounts = b.getUpdateCounts();
                    for (int i = 0; i < updateCounts.length; i++) {
                            System.err.print(updateCounts[i] + "   ");
                    }
                    System.err.println("");
            }
    catch (Exception e) {
        e.printStackTrace();
    }

Как определить строку, из-за которой исключение смогло повторно выполнить пакетную обработку без этой конкретной строки? (Путем обновления поля строки hasError).

В настоящее время я не сохраняю объекты в пакетном режиме, поэтому могу пометить строку, если она вызывает ошибку, пропустить эту строку и перейти к обработке (т.е. сохранить / передать и удалить) другой строки.

Спасибо!

Обновить:

Хорошо, я использовал следующий код для отслеживания строк (если какая-либо строка вызывает ошибку):

        public static void processUpdateCounts(int[] updateCounts) {
            for (int i=0; i<updateCounts.length; i++) {
                if (updateCounts[i] >= 0) {
                    // Successfully executed; the number represents number of affected rows
                    logger.info("Successfully executed: number of affected rows: "+updateCounts[i]);
                } else if (updateCounts[i] == Statement.SUCCESS_NO_INFO) {
                    // Successfully executed; number of affected rows not available
                    logger.info("Successfully executed: number of affected rows not available: "+updateCounts[i]);
                } else if (updateCounts[i] == Statement.EXECUTE_FAILED) {
                    logger.info("Failed to execute: "+updateCounts[i]);
                    // Failed to execute
                }
            }
        }

И добавил строку:

        processUpdateCounts(updateCounts);

так что я могу видеть изменения с ошибкой или без нее, но похоже, что BatchUpdateException не работает?

4 ответа

Создайте слой БД, который поможет выполнить команду. Если команда sql не удалась, повторите ее несколько раз, используя цикл while или что-то еще, если по-прежнему не удалось через несколько раз, зарегистрируйте ее.

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

List<...>paramList = new ArrayList<...>();
for (... params in paramList) {
    stmt.clearParameters();
    stmt.setString(...something involving params...);
    // etc.
}

Таким образом, индекс getUpdateCounts с EXECUTE_FAILED Массив можно использовать для определения того, какие параметры вызвали сбой.

Я использую mysql-connector-java-3.1.14 с MySQL. Обновление в верхней части этого раздела (которое использует исключение BatchUpdateException и getUpdateCounts) работает правильно. Теперь я могу найти проблемную строку в пакетной вставке / обновлении.

Цитаты из Javadoc BatchUpdateException:

Порядок элементов в массиве счетчиков обновлений соответствует порядку, в котором команды были добавлены в пакет.

После того, как команда в пакетном обновлении не выполняется должным образом и генерируется исключение BatchUpdateException, драйвер может или не может продолжать обрабатывать оставшиеся команды в пакете. Если драйвер продолжает обработку после сбоя, массив, возвращенный методом BatchUpdateException.getUpdateCounts, будет иметь элемент для каждой команды в пакете, а не только элементы для команд, которые успешно выполнялись до ошибки. В случае, когда драйвер продолжает обрабатывать команды, элементом массива для любой неудачной команды является Statement.EXECUTE_FAILED.

Другие вопросы по тегам