Java 在JDBC中,当autocommit为false并且没有设置显式保存点时,回滚是好风格还是浪费?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3160756/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In JDBC, when autocommit is false and no explicit savepoints have been set, is it good style or a waste to rollback?
提问by Uri
Say you have the following code:
假设您有以下代码:
Connection conn;
try
{
conn = ... // get connection
conn.setAutoCommit(false);
... // Do some modification queries and logic
conn.commit()
} catch(SQLException e)
{
conn.rollback() // Do we need this?
conn.close()
}
In this code, if there is an exception, is it better style to just close the connection (since autocommit is off), or to explicitly roll back and then close the connection? There are no save points.
在这段代码中,如果出现异常,是关闭连接(因为自动提交已关闭)还是显式回滚然后关闭连接更好?没有保存点。
I feel that it might make sense to add the rollback call because:
我觉得添加回滚调用可能有意义,因为:
1) Someone, in the future, might add save points but forget to add the rollback
1)将来有人可能会添加保存点但忘记添加回滚
2) It improves readability
2)提高可读性
3) It shouldn't cost anything, right ?
3)它不应该花费任何东西,对吗?
But obviously, none of these is particularly compelling. Any standard practice?
但显然,这些都不是特别引人注目。任何标准做法?
Note: I'm aware of the need to do a repeat try/catch on closing and rollback. I actually have a middleware that abstracts the database access and takes care of that, but I was wondering whether adding it was superfluous.
注意:我知道需要在关闭和回滚时重复尝试/捕获。我实际上有一个中间件来抽象数据库访问并处理它,但我想知道添加它是否是多余的。
回答by jbindel
Closing should rollback because it will not commit when the resources are release, but it's good to have your error handling be specific, so if you want to rollback on an exception, do that. Then you can do your cleanup in a finally{} block. The rollback() occurs only on error, in which case your commit() is not successful or was not even reached.
关闭应该回滚,因为它不会在资源释放时提交,但最好让您的错误处理具体化,因此如果您想回滚异常,请执行此操作。然后您可以在 finally{} 块中进行清理。rollback() 仅在错误时发生,在这种情况下,您的 commit() 不成功或什至未达到。
Connection conn = null;
try {
conn = ...
...
conn.commit();
}
catch (SQLException e) {
if (conn != null) {
conn.rollback();
}
}
finally {
if (conn != null) {
conn.close();
}
}
回答by BalusC
The normal idiom is the following:
正常的成语如下:
public void executeSomeQuery() throws SQLException {
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
try (PreparedStatement statement = connection.prepareStatement(SOME_SQL)) {
// Fire transactional queries here.
connection.commit();
} catch (SQLException e) {
connection.rollback();
throw e;
}
}
}
Note that Java 7's try-with-resources statementalways implicitly calls close()
on the resource when the try
block finishes, as if it happens in finally
.
请注意,Java 7 的try-with-resources 语句总是close()
在try
块完成时隐式调用资源,就好像它发生在finally
.
Calling rollback()
is also mandatory when it concerns a pooled connection. Namely, it will reset the transactional state of the connection. The close()
of a pooled connection won't do that, only the commit()
and rollback()
will do that. Not calling rollback()
may lead that the next lease of the pooled connection will still have the (successful) queries of the previous transaction in its memory.
rollback()
当涉及池化连接时,调用也是强制性的。即,它将重置连接的事务状态。该close()
连接池的不会做,只有commit()
和rollback()
将这样做。不调用rollback()
可能会导致池连接的下一个租约在其内存中仍然有前一个事务的(成功)查询。
See also javadoc of Connection#close()
(emphasis not mine):
另请参阅Connection#close()
(重点不是我的)的javadoc :
It is strongly recommendedthat an application explicitly commits or rolls back an active transaction prior to calling the
close
method. If theclose
method is called and there is an active transaction, the results are implementation-defined.
据强烈推荐该应用程序显式提交或辊之前调用备份活动事务
close
的方法。如果close
调用该方法并且存在活动事务,则结果是实现定义的。