简体   繁体   English

如何在批处理中获取包含异常的精确sql查询

[英]How to get exact sql query that contains exception in batch processing

I want to execute the following:我想执行以下操作:

(a transfer to PRESENTATION DB of a row from a fetched row of PROCESSING DB) (从 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();
    }

How can I identify a row that caused the exception to be able to re-execute the batch-processing without this particular row?如何识别导致异常的行,以便能够在没有此特定行的情况下重新执行批处理? (By updating the row's field hasError). (通过更新行的字段 hasError)。

Currently I am not saving the objects by batch so I can mark the row if it causes an error and skip that row and move on to process (ie save/transfer and delete) another row.目前我没有批量保存对象,因此我可以标记该行,如果它导致错误并跳过该行并继续处理(即保存/传输和删除)另一行。

Thanks!谢谢!

Update:更新:

Ok, I used the following code to track the rows (if any row causes an error):好的,我使用以下代码来跟踪行(如果任何行导致错误):

        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
                }
            }
        }

And added the line:并添加了以下行:

        processUpdateCounts(updateCounts);

so I can see changes with or without any error, but it seems like BatchUpdateException isn't working?所以我可以看到有或没有任何错误的更改,但似乎 BatchUpdateException 不起作用?

I'm using mysql-connector-java-3.1.14 with MySQL.我在 MySQL 中使用 mysql-connector-java-3.1.14。 The update at the top of this topic (which uses BatchUpdateException and getUpdateCounts) are working correctly.本主题顶部的更新(使用 BatchUpdateException 和 getUpdateCounts)工作正常。 Now i can find the problematic row in batch insert/update.现在我可以在批量插入/更新中找到有问题的行。

Quotes from the javadoc of BatchUpdateException :来自 BatchUpdateException 的 javadoc 的引用:

The order of elements in an array of update counts corresponds to the order in which commands were added to the batch.更新计数数组中元素的顺序对应于将命令添加到批处理中的顺序。

After a command in a batch update fails to execute properly and a BatchUpdateException is thrown, the driver may or may not continue to process the remaining commands in the batch.在批量更新中的命令无法正确执行并抛出 BatchUpdateException 后,驱动程序可能会也可能不会继续处理批处理中的剩余命令。 If the driver continues processing after a failure, the array returned by the method BatchUpdateException.getUpdateCounts will have an element for every command in the batch rather than only elements for the commands that executed successfully before the error.如果驱动程序在失败后继续处理,则 BatchUpdateException.getUpdateCounts 方法返回的数组将包含批处理中每个命令的元素,而不仅仅是错误前成功执行的命令的元素。 In the case where the driver continues processing commands, the array element for any command that failed is Statement.EXECUTE_FAILED.在驱动程序继续处理命令的情况下,任何失败命令的数组元素是 Statement.EXECUTE_FAILED。

As already pointed out, you get access only to the index of the SQL statement that failed during the batch.正如已经指出的那样,您只能访问批处理期间失败的 SQL 语句的索引。 This means that in order to recreate the same statement that failed to execute you should store parameters in an indexable way, such as:这意味着为了重新创建未能执行的相同语句,您应该以可索引的方式存储参数,例如:

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

This way the index of the getUpdateCounts with EXECUTE_FAILED array can be used to identify which parameters caused the failure.这样,带有EXECUTE_FAILED数组的getUpdateCounts的索引可用于识别导致失败的参数。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM