如何从BatchUpdateException中找到有问题的插入?

时间:2010-09-07 17:34:48

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

当我因为唯一约束违规而导致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数据库,如果相关的话。

提前感谢任何建议。

- 詹姆斯

1 个答案:

答案 0 :(得分:2)

来自BatchUpdateException的Java API文档:

  

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

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