如果发生异常 (SQLException | BatchUpdateException) - Java 重试准备语句批处理
Retry the preparedstatement batches if an exception (SQLException | BatchUpdateException) occurs - Java
我的代码遇到了 SQL 服务器某些事务的死锁问题。所以,我实现了一个重试逻辑来克服同样的问题。现在,我面临一个新问题。问题是,无论何时重试,尝试执行的批处理在从异常中恢复后都将是 empty/cleared。这导致数据丢失 inserts/updates。请帮我解决这个问题。
总结:
如果发生异常(SQLException | BatchUpdateException)
,则重试准备语句批处理
当前实施:
do {
try {
if (isInsert) {
int[] insertRows = psInsert.executeBatch();
psInsert.clearBatch();
System.out.println("insertRowsSuccess:" + Arrays.toString(insertRows));
} else {
int[] updateRows = psUpdate.executeBatch();
psUpdate.clearBatch();
System.out.println("updateRowsSuccess:" + Arrays.toString(updateRows));
}
break;
} catch (BatchUpdateException e) {
conn.rollback();
if (++count == maxTries) {
System.out.println(e.getMessage());
getFailedRecords(e, operation);
}
} catch (SQLException e) {
if (++count == maxTries) {
System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage());
}
}
System.out.println("Tries:" + count);
} while (true);
private static void getFailedRecords(BatchUpdateException ex, String operation) {
int[] updateCount = ex.getUpdateCounts();
ArrayList<Integer> failedRecsList = new ArrayList<Integer>();
int failCount = 0;
for (int i = 0; i < updateCount.length; i++) {
if (updateCount[i] == Statement.EXECUTE_FAILED) {
failCount++;
failedRecsList.add(i);
}
}
System.out.println(operation + " Failed Count: " + failCount);
System.out.println(operation + " FailedRecordsIndex:" + failedRecsList);
}
我认为您应该将 clearBatch()
移到 try
之外。如果您必须重新检查它是插入还是更新,那就这样吧。如果 psInsert
和 psUdate
是相同的 class,或者派生自相同的基础 class(听起来它们应该如此),您可以轻松地在单独的基础中调用它线性法。
我还认为,如果您将此问题提交给 code review,您会得到一些改进代码的好建议。我并不是说这很糟糕,但我认为底层模型还有改进的余地。不过,我对 Java 还不够熟悉。
执行后,无论批处理成功与否,批处理都会被清除。您需要重新填充批处理才能重试。
我的代码遇到了 SQL 服务器某些事务的死锁问题。所以,我实现了一个重试逻辑来克服同样的问题。现在,我面临一个新问题。问题是,无论何时重试,尝试执行的批处理在从异常中恢复后都将是 empty/cleared。这导致数据丢失 inserts/updates。请帮我解决这个问题。
总结: 如果发生异常(SQLException | BatchUpdateException)
,则重试准备语句批处理当前实施:
do {
try {
if (isInsert) {
int[] insertRows = psInsert.executeBatch();
psInsert.clearBatch();
System.out.println("insertRowsSuccess:" + Arrays.toString(insertRows));
} else {
int[] updateRows = psUpdate.executeBatch();
psUpdate.clearBatch();
System.out.println("updateRowsSuccess:" + Arrays.toString(updateRows));
}
break;
} catch (BatchUpdateException e) {
conn.rollback();
if (++count == maxTries) {
System.out.println(e.getMessage());
getFailedRecords(e, operation);
}
} catch (SQLException e) {
if (++count == maxTries) {
System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage());
}
}
System.out.println("Tries:" + count);
} while (true);
private static void getFailedRecords(BatchUpdateException ex, String operation) {
int[] updateCount = ex.getUpdateCounts();
ArrayList<Integer> failedRecsList = new ArrayList<Integer>();
int failCount = 0;
for (int i = 0; i < updateCount.length; i++) {
if (updateCount[i] == Statement.EXECUTE_FAILED) {
failCount++;
failedRecsList.add(i);
}
}
System.out.println(operation + " Failed Count: " + failCount);
System.out.println(operation + " FailedRecordsIndex:" + failedRecsList);
}
我认为您应该将 clearBatch()
移到 try
之外。如果您必须重新检查它是插入还是更新,那就这样吧。如果 psInsert
和 psUdate
是相同的 class,或者派生自相同的基础 class(听起来它们应该如此),您可以轻松地在单独的基础中调用它线性法。
我还认为,如果您将此问题提交给 code review,您会得到一些改进代码的好建议。我并不是说这很糟糕,但我认为底层模型还有改进的余地。不过,我对 Java 还不够熟悉。
执行后,无论批处理成功与否,批处理都会被清除。您需要重新填充批处理才能重试。