使用 EmbeddedDatabase H2 进行测试时获取 JdbcBatchUpdateException
Getting JdbcBatchUpdateException while testing with EmbeddedDatabase H2
我在尝试使用 EmbeddedDatabase H2 测试我的代码时遇到奇怪的异常:
java.lang.RuntimeException:
java.lang.RuntimeException: org.h2.jdbc.JdbcBatchUpdateException: Timeout trying to lock table "CO_SCENARIO_1"; SQL statement:
UPDATE CO_SCENARIO_1 SET VALUE = ? WHERE ATTRIBUTE = ? AND MODIFIER = ? [50200-156]
at de.telekom.skses.test.dao.DatabaseFileConverterTest.fromFile(DatabaseFileConverterTest.java:99)
这是我要测试的部分代码:
case "overriddenVariables.txt": {
try (Scanner sc = new Scanner(bOut.toString())) {
try (Connection con = dataSource.getConnection()) {
String aQuery = "UPDATE $tableName SET VALUE = ? WHERE ATTRIBUTE = ? AND MODIFIER = ?";
String line = "";
if (sc.hasNext()) {
line = sc.nextLine();
}
while (sc.hasNext()) {
if (line.startsWith("+")) {
String setting = line.substring(1);
try (PreparedStatement ps = con.prepareStatement(aQuery.replace("$tableName", setting))) {
while (sc.hasNext() && !(line = sc.nextLine()).startsWith("+")) {
int del1 = line.indexOf(":");
int del2 = line.indexOf(':', del1 + 1);
String attr = line.substring(0, del1);
String modifier = line.substring(del1 + 1, del2);
String value = line.substring(del2 + 1, line.length());
Clob myClob = con.createClob();
myClob.setString(1, value);
ps.setClob(1, myClob);
ps.setString(2, attr);
ps.setString(3, modifier);
ps.addBatch();
}
ps.executeBatch();
}
}
}
} catch (SQLException e) {
logger.error("Error", e);
throw new RuntimeException(e);
}
} catch (Exception ex) {
logger.error("Error", ex);
throw new RuntimeException(ex);
}
break;
}
Whosebug 说我应该设置锁定超时,但我没有找到如何为 EmbeddedDatabase 设置它。此外,在以前的版本中,我为每个查询打开了新的 PreparedStatement,为每个 PreparedStatement 打开了新的连接,一切都运行良好,但我不明白为什么现在不行了。你能解释一下我必须做些什么才能让它再次工作吗?
抱歉,如果有什么不正确的地方,我是 Java EE 的新手。
我记得在嵌入式模式下使用 H2,它存在并发问题。这可能就是为什么您在 table 上获得锁定超时的原因,因为当您尝试执行下一批时,table 仍然从上一批更新。每次关闭连接和 preparedStatement 时,执行时间会更短,因此您不会超时。
您是否尝试过按照 post 中所述添加到数据库URL ;MVCC=true
?如果这不能解决问题,是否真的有必要使用批处理进行更新?
编辑:我之前链接的 post,链接到 h2 website,您可以在其中找到有关如何通过将 ;LOCK_TIMEOUT=10000
添加到数据库 URL。这会将其更改为 10 秒,标准为 1 秒
我在尝试使用 EmbeddedDatabase H2 测试我的代码时遇到奇怪的异常:
java.lang.RuntimeException:
java.lang.RuntimeException: org.h2.jdbc.JdbcBatchUpdateException: Timeout trying to lock table "CO_SCENARIO_1"; SQL statement:
UPDATE CO_SCENARIO_1 SET VALUE = ? WHERE ATTRIBUTE = ? AND MODIFIER = ? [50200-156]
at de.telekom.skses.test.dao.DatabaseFileConverterTest.fromFile(DatabaseFileConverterTest.java:99)
这是我要测试的部分代码:
case "overriddenVariables.txt": {
try (Scanner sc = new Scanner(bOut.toString())) {
try (Connection con = dataSource.getConnection()) {
String aQuery = "UPDATE $tableName SET VALUE = ? WHERE ATTRIBUTE = ? AND MODIFIER = ?";
String line = "";
if (sc.hasNext()) {
line = sc.nextLine();
}
while (sc.hasNext()) {
if (line.startsWith("+")) {
String setting = line.substring(1);
try (PreparedStatement ps = con.prepareStatement(aQuery.replace("$tableName", setting))) {
while (sc.hasNext() && !(line = sc.nextLine()).startsWith("+")) {
int del1 = line.indexOf(":");
int del2 = line.indexOf(':', del1 + 1);
String attr = line.substring(0, del1);
String modifier = line.substring(del1 + 1, del2);
String value = line.substring(del2 + 1, line.length());
Clob myClob = con.createClob();
myClob.setString(1, value);
ps.setClob(1, myClob);
ps.setString(2, attr);
ps.setString(3, modifier);
ps.addBatch();
}
ps.executeBatch();
}
}
}
} catch (SQLException e) {
logger.error("Error", e);
throw new RuntimeException(e);
}
} catch (Exception ex) {
logger.error("Error", ex);
throw new RuntimeException(ex);
}
break;
}
Whosebug 说我应该设置锁定超时,但我没有找到如何为 EmbeddedDatabase 设置它。此外,在以前的版本中,我为每个查询打开了新的 PreparedStatement,为每个 PreparedStatement 打开了新的连接,一切都运行良好,但我不明白为什么现在不行了。你能解释一下我必须做些什么才能让它再次工作吗?
抱歉,如果有什么不正确的地方,我是 Java EE 的新手。
我记得在嵌入式模式下使用 H2,它存在并发问题。这可能就是为什么您在 table 上获得锁定超时的原因,因为当您尝试执行下一批时,table 仍然从上一批更新。每次关闭连接和 preparedStatement 时,执行时间会更短,因此您不会超时。
您是否尝试过按照 post 中所述添加到数据库URL ;MVCC=true
?如果这不能解决问题,是否真的有必要使用批处理进行更新?
编辑:我之前链接的 post,链接到 h2 website,您可以在其中找到有关如何通过将 ;LOCK_TIMEOUT=10000
添加到数据库 URL。这会将其更改为 10 秒,标准为 1 秒