4

一意の制約違反の結果として BatchUpdateException が発生した場合、バッチ挿入のどのレコードが違反しているかを特定する方法はありますか? たとえば、PreparedStatement.executeBatch() を呼び出してバッチ挿入を実行していて、「ORA-00001: 一意の制約 (ABC.SYS_123) 違反」が原因である BatchUpdateException をキャッチするとします。Eclipse を使用してデバッグする場合、これはこの例外から得られる情報とほぼ同じですが、一意の制約違反の原因となっている実際の挿入を特定したいと思います。この情報を見つける方法はありますか?

私のコードは現在(多かれ少なかれ)次のようになっています。

public void batchInsert(final Collection<MyObject> objectCollection)
{
    try
    {
        if (connection == null)
        {
            connection = getJdbcTemplate().getDataSource().getConnection();
        }

        // get the last entity ID value so we can know where to begin
        Long entityId = getJdbcTemplate().queryForLong("SELECT MAX(" + MyObject.ID_COLUMN_NAME +
                                                       ") FROM " + MyObject.TABLE_NAME);
        entityId++;

        // get a date to use for the created and updated dates
        Date now = new Date(new java.util.Date().getTime());

        // set auto commit to false so we can batch save without committing each individual insert
        connection.setAutoCommit(false);

        // create the prepared statement
        String insertSql = "INSERT INTO " + MyObject.TABLE_NAME + " (" +
                           MyObject.ID_COLUMN_NAME + ", VALUE_1, VALUE_2) " +
                           "VALUES (?, ?, ?)";
        PreparedStatement preparedStatement = connection.prepareStatement(insertSql);

        // add a batch entry for each of the SurfaceMetObservations objects
        for (MyObject object : objectCollection)
        {
            preparedStatement.setLong(1, entityId);
            preparedStatement.setBigDecimal(2, object.getValue1());
            preparedStatement.setBigDecimal(3, object.getValue2());
            preparedStatement.addBatch();
            entityId++;
        }

        int updateCounts[] = preparedStatement.executeBatch();
        preparedStatement.close();
        if (confirmUpdateCounts(updateCounts))
        {
            connection.commit();
        }
        else
        {
            connection.rollback();
            throw new RuntimeException("One or more inserts failed to execute.");
        }
    }
    catch (SQLException ex)
    {
        throw new RuntimeException(ex);
    }
}

関連する場合に備えて、Spring の JdbcTemplate と Oracle 11G データベースを使用しています。

アドバイスをよろしくお願いします。

--ジェームズ

4

1 に答える 1

3

BatchUpdateExceptionの Java API ドキュメントから:

バッチ更新内のコマンドが正しく実行されず、BatchUpdateException がスローされた後、ドライバーはバッチ内の残りのコマンドの処理を続行する場合と続行しない場合があります。エラーが発生した後もドライバーが処理を続行する場合、メソッド BatchUpdateException.getUpdateCounts によって返される配列には、エラーの前に正常に実行されたコマンドの要素だけでなく、バ​​ッチ内のすべてのコマンドの要素が含まれます。ドライバーがコマンドの処理を続行する場合、失敗したコマンドの配列要素は Statement.EXECUTE_FAILED です。

現在、使用している Oracle JDBC ドライバーの動作についてはわかりませんが、言及されている手法のいずれかが機能することは明らかです。BatchUpdateException.getUpdateCounts の呼び出しによって返される配列に N 個の要素がある場合は、バッチ内の N 個の要素が処理されました。または、返された配列がバッチ処理されたステートメントの数と同じサイズである場合、値が Statement.EXECUTE_FAILED であるすべての配列要素がバッチで実行に失敗したことになります。

于 2010-09-07T22:39:42.843 に答える