21

每次执行我的程序时,我都在执行 JDBC 批量插入(一次大约插入 1000 行)。但我无法正确处理某些记录引发的异常。

假设 1000 条记录中的第 100 条记录由于无效数据或某个值的大小超过列大小而引发异常。一旦发生异常,剩余的记录就不会被插入,程序就会在两者之间失败。

我想要的是即使第 100 条记录抛出异常,其余的插入应该在我的程序结束之前像往常一样发生。

我无法理解如何实现这一目标。请建议。

编辑:

这是我在我的应用程序中用于批量插入的示例代码。假设结果集有大约 1000 条记录。

PreparedStatement ps = null;
while(rs.next()){
  //Retrieve the value and set it to a Prepared statement

  String name = rs.getString("Name");
  int age = rs.getInt("Age");
  ps.setInt(1, age);
  ps.setString(2, name);

  //Finally invoke addBatch
  ps.addBatch();
}

//Finally call the executeBatch method
ps.executeBatch();

如果第 100 条记录引发异常,那么我只想从第 100 条和第 1000 条记录触发该过程。有什么方法可以做到这一点,以便我可以从引发异常的记录重新启动该过程,直到再次结束?如何做到这一点?

4

2 回答 2

28

您声明您正在执行批量 SQL 语句,所以我假设您正在使用executeBatch. 当你executeBatch做一批语句时,有的语句可能成功,有的语句可能失败。如果一条语句失败,这并不意味着 JDBC 驱动程序会回滚成功的语句。如果一条语句失败,JDBC 驱动程序可能会选择尝试执行批处理中的所有语句,或者一旦语句失败,它可能会选择停止执行批处理中的语句(听起来您正在使用的驱动程序选择停止执行语句为一旦出现故障)。

当批处理中的一个语句失败时,您应该得到一个BatchUpdateException. 在您的异常处理程序中,您需要调用getUpdateCounts. 这将为您提供一个数组int,告诉您语句更新了多少行,Statement.SUCCESS_NO_INFO指示语句成功但没有行数可用,或者Statement.EXECUTE_FAILED指示语句失败。如果前 99 条语句成功,第 100 条语句产生错误,其余语句未执行,则应返回一个 100 元素数组,其中前 99 个元素表示成功,第 100 个元素表示Statement.EXECUTE_FAILED. 然后,您的代码将需要重试那些未执行的语句(在本例中为语句 101-1000)。

于 2012-07-02T17:28:46.680 回答
0

在没有看到任何代码的情况下,我能给出的最佳建议是在执行插入的代码周围包裹一个 try/catch 块。您可能还需要在每次插入时提交插入(假设事务连接)。这将导致处理速度稍慢,但允许您的程序继续。

我认为更干净的方法是在插入之前尝试预先验证记录。如果我们一次只讨论 1000 条记录,这应该不会造成太大的处理负载。

于 2012-07-02T17:22:08.207 回答