0

Excelファイルからテーブルにデータを挿入しようとしています。次のように2つのExcelファイルがあります。

Test2:
5/12/2012     5/18/2012 ABQ ANC 1   52
5/12/2012     5/18/2012 ABQ ANC 2   30
5/12/2012     5/18/2012 ABQ ANC 3   34
5/12/2012     5/18/2012 ABQ ANC 4   41
5/12/2012     5/18/2012 ABQ ANC 5   53--->duplicate row
5/12/2012     5/18/2012 ABQ ANC 6   18
5/12/2012      5/18/2012    ABQ ANC 7   4
5/12/2012      5/18/2012    ABQ ATL 1   389
5/12/2012     5/18/2012 ABQ ATL 2   312

テスト1:

5/12/2012     5/18/2012 ABQ ATL 4   259
5/12/2012     5/18/2012 ABQ ATL 5   362
5/12/2012     5/18/2012 ABQ ATL 6   240
5/12/2012     5/18/2012 ABQ ATL 7   88
5/12/2012     5/18/2012 ABQ ANC 5   53--->duplicate row
5/12/2012     5/18/2012 ABQ AUS 2   2
5/12/2012     5/18/2012 ABQ BDL 1   164
5/12/2012     5/18/2012 ABQ BDL 2   128
5/12/2012     5/18/2012 ABQ BDL 3   132

私のテーブルは、そもそも空です。最初のファイル (test2) を挿入すると、正常に動作します。2 番目のファイル (test1) を挿入すると、test1 の 5 行目で「一意の制約違反」例外が発生するはずです。テストのために意図的にその行を複製しました。挿入を行うために次のコードを書きました。ご覧のとおり、バッチサイズは 3 です。

2 番目のファイルを挿入すると、コードは最初のバッチ (最初の 3 行) を正常に実行します。2 番目のバッチ (行 4 ~ 6) では、行 (5) の 1 つが重複しているため、BatchUpdatException がスローされます。その例外をキャッチし、catch ブロックで各行 (行 4 ~ 6) を一度に 1 つずつ処理します。したがって、行 4 の挿入は正常に機能するはずです。しかし、そうではありません。代わりに sqlException をスローします。行 5 も同様に例外をスローします (重複行)。しかし、6行目はそうではありません。行 6 executeUpdate() は正常に実行されます。この時点で、データベース テーブルを見ると、行 4 も行 6 と共にテーブルに挿入されていることがわかります。なぜこれが起こるのでしょうか。行 4 で例外がスローされただけなのでしょうか?

私の目的は、重複行がどこにあるかをユーザーに知らせることです。この異常な動作のため、ユーザーが 2 番目のファイルを挿入しようとすると、行 4 と行 5 に重複する行があることが通知されます。

String sqlStatement = "INSERT INTO DMD_VOL_UPLOAD (ORIGIN, DESTINATION, DAY_OF_WEEK, EFFECTIVE_DATE, DISCONTINUE_DATE, VOLUME)";
    int batchSize=3;
    sqlStatement += " VALUES(?, ?, ?, ?, ?, ?)";
    con = session.connection();
        pstmt = con.prepareStatement(sqlStatement);
    for(currentRow=1; currentRow<=rowCount; currentRow++){
        try{
                forecastBatch = (ForecastBatch) list.get(currentRow-1);                                 
                pstmt = (PreparedStatement) prepareStatement(pstmt, forecastBatch);         
                pstmt.addBatch();               
                if(currentRow % batchSize == 0 || currentRow==rowCount){
                    updateCounts = pstmt.executeBatch();
                    con.commit();
                    pstmt.clearBatch();
                }                           
        }catch(BatchUpdateException e){
                int endPoint = currentRow;
                int i;
                for(i=currentRow-batchSize; i<endPoint; i++){
                    forecastBatch = (ForecastBatch) list.get(i);
                    try{
                        pstmt = (PreparedStatement) prepareStatement(pstmt, forecastBatch); 
                        pstmt.executeUpdate();**strong text**
                        con.commit();
                    }catch(SQLException ex){
                        errorRowNum = errorRowNum + (i+1) + ", ";
                        ex.printStackTrace();
                    }   
                }
        }catch(SQLException e){
                e.printStackTrace();
        }
    }//end of the first for loop
4

1 に答える 1

1

ステートメントのバッチを実行executeBatchすると、一部のステートメントが成功し、一部のステートメントが失敗する場合があります。1 つのステートメントが失敗しても、JDBC ドライバーが成功したステートメントをロールバックするわけではありません。JDBC ドライバーは、1 つのステートメントが失敗した場合にバッチ内のすべてのステートメントを実行しようとするか、ステートメントが失敗するとバッチ内のステートメントの実行を停止することを選択する場合があります (使用しているドライバーがステートメントの実行を停止することを選択したように聞こえます)。障害が発生するとすぐに)。

を取得したら、BatchUpdateExceptionに電話する必要がありますgetUpdateCountsintこれにより、ステートメントが更新されたStatement.SUCCESS_NO_INFO行数、ステートメントは成功したが行数が利用できなかったことを示す の配列が得られます。Statement.EXECUTE_FAILEDステートメントが失敗したことを示します。バッチの最初のステートメント (スプレッドシートの 4 行目) が成功し、バッチの 2 番目のステートメント (スプレッドシートの 5 行目) が失敗したことを示す 2 要素の配列が返されると思います。配列に 3 番目の要素がないことは、バッチの 3 番目のステートメント (スプレッドシートの行 6) が実行されなかったことを示します。再試行コードは、実行されなかったステートメントのみを再試行する必要があります。BatchUpdateExceptionこの場合、最初のステートメントが成功し、2 番目のステートメントが失敗したことがすでに示されているため、3 番目のステートメント (スプレッドシートの行 6) のみを再試行する必要があります。

于 2012-04-27T20:44:11.187 に答える