4

我想执行以下操作:

(从 PROCESSING DB 的提取行中转移到 PRESENTATION DB 的行)

    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

4 回答 4

0

我将 mysql-connector-java-3.1.14 与 MySQL 一起使用。本主题顶部的更新(使用 BatchUpdateException 和 getUpdateCounts)工作正常。现在我可以在批量插入/更新中找到有问题的行。

于 2013-05-13T12:56:22.007 回答
0

来自 BatchUpdateException 的 javadoc 的引用:

更新计数数组中元素的顺序对应于将命令添加到批处理中的顺序。

在批处理更新中的命令无法正确执行并引发 BatchUpdateException 后,驱动程序可能会或可能不会继续处理批处理中剩余的命令。如果驱动程序在失败后继续处理,则 BatchUpdateException.getUpdateCounts 方法返回的数组将为批处理中的每个命令都有一个元素,而不仅仅是在错误之前成功执行的命令的元素。在驱动程序继续处理命令的情况下,任何失败的命令的数组元素都是 Statement.EXECUTE_FAILED。

于 2011-03-07T15:03:16.473 回答
0

正如已经指出的,您只能访问批处理期间失败的 SQL 语句的索引。这意味着为了重新创建未能执行的相同语句,您应该以可索引的方式存储参数,例如:

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

这样,getUpdateCountswithEXECUTE_FAILED数组的索引可用于识别导致失败的参数。

于 2011-03-07T15:29:41.907 回答
0

创建一个有助于执行命令的数据库层,如果 sql 命令失败,则使用 while 循环或其他方法重试几次,如果几次后仍然失败,则记录它。

于 2011-05-08T09:24:22.760 回答