【问题标题】:How to find the offending insertion from a BatchUpdateException?如何从 BatchUpdateException 中找到有问题的插入?
【发布时间】:2011-04-09 08:02:51
【问题描述】:

当我因违反唯一约束而出现 BatchUpdateException 时,是否有办法确定批量插入中的哪条记录违反了?例如,假设我正在通过调用 PreparedStatement.executeBatch() 执行批量插入,并且我捕获了 BatchUpdateException,它的原因是“ORA-00001:违反了唯一约束 (ABC.SYS_123)”。使用 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 数据库,以防万一。

提前感谢您的任何建议。

--詹姆斯

【问题讨论】:

    标签: java oracle jdbc exception-handling ora-00001


    【解决方案1】:

    来自BatchUpdateException的Java API文档:

    在批量更新命令后 未能正确执行并且 抛出 BatchUpdateException 时, 司机可能会也可能不会继续 处理剩下的命令 批。如果司机继续 处理失败后,数组 方法返回 BatchUpdateException.getUpdateCounts 每个命令都有一个元素 在批处理中而不是仅在元素中 对于执行的命令 在错误之前成功。在里面 司机继续的情况 处理命令,数组元素 对于任何失败的命令是 Statement.EXECUTE_FAILED。

    现在,我不确定您正在使用的 Oracle JDBC 驱动程序的行为,但很明显,提到的任何一种技术都应该有效 - 如果调用 BatchUpdateException 返回的数组中有 N 个元素。 getUpdateCounts,则该批次中的 N 个元素已被处理。或者,如果返回的数组的大小与批处理语句的数量相同,那么所有值为 Statement.EXECUTE_FAILED 的数组元素在批处理中都将执行失败。

    【讨论】:

    • 感谢 Vineet,让我注意到这些非常有用的信息。非常感谢!
    猜你喜欢
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-04
    相关资源
    最近更新 更多