簡體   English   中英

如何在批處理中獲取包含異常的精確sql查詢

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

我想執行以下操作:

(從 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 不起作用?

我在 MySQL 中使用 mysql-connector-java-3.1.14。 本主題頂部的更新(使用 BatchUpdateException 和 getUpdateCounts)工作正常。 現在我可以在批量插入/更新中找到有問題的行。

來自 BatchUpdateException 的 javadoc 的引用:

更新計數數組中元素的順序對應於將命令添加到批處理中的順序。

在批量更新中的命令無法正確執行並拋出 BatchUpdateException 后,驅動程序可能會也可能不會繼續處理批處理中的剩余命令。 如果驅動程序在失敗后繼續處理,則 BatchUpdateException.getUpdateCounts 方法返回的數組將包含批處理中每個命令的元素,而不僅僅是錯誤前成功執行的命令的元素。 在驅動程序繼續處理命令的情況下,任何失敗命令的數組元素是 Statement.EXECUTE_FAILED。

正如已經指出的那樣,您只能訪問批處理期間失敗的 SQL 語句的索引。 這意味着為了重新創建未能執行的相同語句,您應該以可索引的方式存儲參數,例如:

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

這樣,帶有EXECUTE_FAILED數組的getUpdateCounts的索引可用於識別導致失敗的參數。

創建一個幫助執行命令的數據庫層,如果 sql 命令失敗,則使用 while 循環或其他方法重試幾次,如果幾次后仍然失敗,則記錄它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM