为什么当我没有执行回滚时"Cannot invoke a rollback operation when the AutoCommit mode is set to "收到真正的"."?



执行以下操作会导致异常"当自动提交模式设置为"true"时无法调用回滚操作。

java.sql.Connection connection = DriverManager.getConnection(connectionString);
com.ibatis.common.jdbc.ScriptRunner scriptRunner = new ScriptRunner(connection, true, true);
java.io.StringReader reader = new StringReader("PRINT 1;");
scriptRunner.runScript(reader);
// Cannot invoke a rollback operation when the AutoCommit mode is set to "true".

我的代码中没有引用回滚,我找不到任何选项来禁用它。我已经独立查看了.xml并尝试设置 jta=false。我在sqlMapConfig\transactionManager上找到并设置了commitRequired=false,这是真的,但这并没有区别。

如果答案存在,我无法找到它。我发现的只是有人说"当然你不能回滚",结果是禁用自动提交。我不要求回滚,那么它从何而来? 根据 https://www.programcreek.com/java-api-examples/index.php?api=com.ibatis.common.jdbc.ScriptRunner 示例 3,我正在做的事情应该有效。

我想在自动提交模式(默认的 MS SQL Server 模式(下执行脚本,而不涉及或强制我执行任何事务,除了围绕 sql 脚本中每个单独语句的自动提交事务。我不想IMPLICIT_TRANSACTIONS,没有开始事务,没有提交,绝对没有回滚。

谢谢你的时间

堆栈跟踪:

com.microsoft.sqlserver.jdbc.SQLServerException: Cannot invoke a rollback operation when the AutoCommit mode is set to "true".
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:191)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.rollback(SQLServerConnection.java:2037)
at com.ibatis.common.jdbc.ScriptRunner.runScript(ScriptRunner.java:222)
at com.ibatis.common.jdbc.ScriptRunner.runScript(ScriptRunner.java:114)
at com.metric.DebugTests.DebugAutoCommit(DebugTests.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

基于对ScriptRunner 的快速浏览(不是问题中的确切版本,但足够接近(,我们可以看到以下代码

if (!autoCommit) {
conn.commit();
}

现在这很好,我们仅在自动提交未打开时才提交。但是,如果引发异常,则会执行 finally 子句,并且不考虑自动提交:

} finally {
conn.rollback();
flush();
}

这将导致丢失原始异常详细信息。

由于如果设置了记录器,异常会打印日志,因此我建议执行以下操作:

scriptRunner.setErrorLogWriter(somePrintWriter); // Some PrintWriter, maybe to a file

这样,您将找出原始异常。这也绝对是一个错误,因此需要报告(似乎我没有 github 凭据,因此拥有这些凭据的人可能会提出问题(或者嘿,为什么不提交拉取请求((。

如果您将自动提交设置为关闭,那么您有责任保存您在数据库上的工作,因此在每个成功任务之后,您必须执行提交命令, 要关闭自动提交,请使用connection.setAutoCommit(false)当你的工作完成后,然后执行connection.commit()将更改保存到数据库 或者,如果出现任何错误,请执行回滚命令connection.rollback()希望它嘿嘿!

相关内容

最新更新