当由于唯一约束冲突而导致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数据库。
在此先感谢您的任何建议。
- 詹姆士
最佳答案
从BatchUpdateException的Java API文档中:
批量更新中的命令后
无法正确执行,并且
抛出BatchUpdateException,
驾驶员可能会或可能不会继续
处理剩余的命令
批量。如果驱动程序继续
失败后处理,数组
方法返回
BatchUpdateException.getUpdateCounts
每个命令都会有一个元素
在批处理中,而不是仅在元素中
对于执行的命令
错误之前成功。在里面
驱动程序继续的情况
处理命令,数组元素
对于任何失败的命令是
Statement.EXECUTE_FAILED。
现在,我不确定您使用的Oracle JDBC驱动程序的行为,但是很明显,提到的任何一种技术都可以工作-如果调用BatchUpdateException.getUpdateCounts返回的数组中有N个元素,则批次中的N个元素已被处理。或者,如果返回的数组的大小与批处理语句的大小相同,则所有值为Statement.EXECUTE_FAILED的数组元素将在批处理中执行失败。