在哪里关闭 java PreparedStatements 和 ResultSets?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/321418/
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
Where to close java PreparedStatements and ResultSets?
提问by MCS
Consider the code:
考虑代码:
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.createStatement(myQueryString);
rs = ps.executeQuery();
// process the results...
} catch (java.sql.SQLException e) {
log.error("an error!", e);
throw new MyAppException("I'm sorry. Your query did not work.");
} finally {
ps.close();
rs.close();
}
The above does not compile, because both PreparedStatement.close()
and ResultSet.close()
throw a java.sql.SQLException
. So do I add a try/catch block to the finally clause? Or move the close statements into the try clause? Or just not bother calling close?
上面没有编译,因为都PreparedStatement.close()
和ResultSet.close()
抛出java.sql.SQLException
。那么我要在 finally 子句中添加一个 try/catch 块吗?或者将 close 语句移到 try 子句中?或者只是不想打扰关闭?
采纳答案by Michael Myers
For file I/O, I generally add a try/catch to the finally block. However, you must be careful not to throw any exceptions from the finally block, since they will cause the original exception (if any) to be lost.
对于文件 I/O,我通常会在 finally 块中添加一个 try/catch。但是,您必须小心不要从 finally 块中抛出任何异常,因为它们会导致原始异常(如果有)丢失。
See this articlefor a more specific example of database connection closing.
有关数据库连接关闭的更具体示例,请参阅本文。
回答by asalamon74
Do no omit calling close. It may cause problems.
不要省略调用close。它可能会导致问题。
I prefer adding try/catch block to the finally.
我更喜欢在 finally 中添加 try/catch 块。
回答by Steve B.
If you're really hand-rolling your own jdbc it definitely gets messy. The close() in the finally needs to get wrapped with its own try catch, which, at the very least, is ugly. You can't skip the close, although the resources will get cleared when the connection is closed (which might not be right away, if you're using a pool). Actually, one of the main selling points of using a framework (e.g. hibernate) to manage your db access is to manage the connection and result set handling so you don't forget to close.
如果你真的手动滚动你自己的 jdbc,它肯定会变得混乱。finally 中的 close() 需要用它自己的 try catch 包裹,这至少是丑陋的。您不能跳过关闭,尽管在连接关闭时资源将被清除(如果您使用的是池,则可能不会立即清除)。实际上,使用框架(例如休眠)来管理您的数据库访问的主要卖点之一是管理连接和结果集处理,这样您就不会忘记关闭。
You can do something simple like this, which at least hides the mess, and guarantees that you don't forget something.
你可以做一些像这样简单的事情,至少可以隐藏混乱,并保证你不会忘记一些事情。
public static void close(ResultSet rs, Statement ps, Connection conn)
{
if (rs!=null)
{
try
{
rs.close();
}
catch(SQLException e)
{
logger.error("The result set cannot be closed.", e);
}
}
if (ps != null)
{
try
{
ps.close();
} catch (SQLException e)
{
logger.error("The statement cannot be closed.", e);
}
}
if (conn != null)
{
try
{
conn.close();
} catch (SQLException e)
{
logger.error("The data source connection cannot be closed.", e);
}
}
}
and then,
进而,
finally {
close(rs, ps, null);
}
回答by Chris Nava
I use this..
我用这个。。
finally
{
if (ps != null) ps.close();
if (rs != null) rs.close();
}
回答by Jon Skeet
I usually have a utility method which can close things like this, including taking care not to try to do anything with a null reference.
我通常有一个实用方法可以关闭这样的事情,包括注意不要尝试使用空引用做任何事情。
Usually if close()
throws an exception I don't actually care, so I just log the exception and swallow it - but another alternative would be to convert it into a RuntimeException
. Either way, I recommend doing it in a utility method which is easy to call, as you may well need to do this in many places.
通常如果close()
抛出异常我实际上并不关心,所以我只是记录异常并吞下它 - 但另一种选择是将其转换为RuntimeException
. 无论哪种方式,我都建议使用易于调用的实用方法来执行此操作,因为您可能在许多地方都需要执行此操作。
Note that your current solution won't close the ResultSet if closing the PreparedStatement fails - it's better to use nested finally blocks.
请注意,如果关闭 PreparedStatement 失败,您当前的解决方案不会关闭 ResultSet - 最好使用嵌套的 finally 块。
回答by BraveSirFoobar
Don't waste your time coding low-level exception management, use an higher-level API like Spring-JDBC, or a custom wrapper around connection/statement/rs objects, to hide the messy try-catch ridden code.
不要浪费时间编码低级异常管理,使用更高级别的 API(如 Spring-JDBC)或围绕 connection/statement/rs 对象的自定义包装器来隐藏杂乱的 try-catch 代码。
回答by erickson
In Java 7, you should not close them explicitly, but use automatic resource managementto ensure that resourcesare closed and exceptions are handled appropriately. Exception handling works like this:
在 Java 7 中,您不应该显式关闭它们,而是使用自动资源管理来确保资源关闭并正确处理异常。异常处理是这样工作的:
Exception in try | Exception in close | Result -----------------+--------------------+---------------------------------------- No | No | Continue normally No | Yes | Throw the close() exception Yes | No | Throw the exception from try block Yes | Yes | Add close() exception to main exception | | as "suppressed", throw main exception
Hopefully that makes sense. In allows pretty code, like this:
希望这是有道理的。在允许漂亮的代码,像这样:
private void doEverythingInOneSillyMethod(String key)
throws MyAppException
{
try (Connection db = ds.getConnection()) {
db.setReadOnly(true);
...
try (PreparedStatement ps = db.prepareStatement(...)) {
ps.setString(1, key);
...
try (ResultSet rs = ps.executeQuery()) {
...
}
}
} catch (SQLException ex) {
throw new MyAppException("Query failed.", ex);
}
}
Prior to Java 7, it's best to use nested finally blocks, rather than testing references for null.
在 Java 7 之前,最好使用嵌套的 finally 块,而不是测试 null 的引用。
The example I'll show might look ugly with the deep nesting, but in practice, well-designed code probably isn't going to create a connection, statement, and results all in the same method; often, each level of nesting involves passing a resource to another method, which uses it as a factory for another resource. With this approach, exceptions from a close()
will mask an exception from inside the try
block. That can be overcome, but it results in even more messy code, and requires a custom exception class that provides the "suppressed" exception chaining present in Java 7.
我将展示的示例在深度嵌套的情况下可能看起来很丑,但实际上,设计良好的代码可能不会以相同的方法创建连接、语句和结果;通常,每一级嵌套都涉及将资源传递给另一个方法,该方法将其用作另一个资源的工厂。使用这种方法,来自 aclose()
的异常将屏蔽try
块内部的异常。这可以克服,但它会导致代码更加混乱,并且需要一个自定义异常类来提供 Java 7 中存在的“被抑制的”异常链。
Connection db = ds.getConnection();
try {
PreparedStatement ps = ...;
try {
ResultSet rs = ...
try {
...
}
finally {
rs.close();
}
}
finally {
ps.close();
}
}
finally {
db.close();
}
回答by erickson
Also note:
另请注意:
"When a Statement object is closed, its current ResultSet object, if one exists, is also closed. "
“当一个 Statement 对象关闭时,它当前的 ResultSet 对象(如果存在)也将关闭。”
http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Statement.html#close()
http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Statement.html#close()
It should be sufficient to close only the PreparedStatement in a finally, and only if it is not already closed. If you want to be really particular though, close the ResultSet FIRST, not after closing the PreparedStatement (closing it after, like some of the examples here, should actually guarantee an exception, since it is already closed).
仅在 finally 中关闭 PreparedStatement 就足够了,并且仅当它尚未关闭时。但是,如果您真的想特别注意,请先关闭 ResultSet,而不是在关闭 PreparedStatement 之后(之后关闭它,就像这里的一些示例一样,实际上应该保证一个异常,因为它已经关闭了)。
回答by Kris
focus finally clause,
焦点最后条款,
finally {
try {
rs.close();
ps.close();
} catch (Exception e) {
// Do something
}
}
I think you have to modify 2 points.
我认为你必须修改2点。
First, use try & catch again in fainlly clause.
首先,在fainlly 子句中再次使用try & catch。
Second, do rs.close() before doing ps.close().
其次,在做 ps.close() 之前先做 rs.close()。
回答by Guido
If your are using Java 7 you can use the improvements in the exception handling mechanisms in those classes that implement AutoCloseable(i.e. PreparedStatement
, Resultset
)
如果您使用的是 Java 7,您可以使用实现AutoCloseable 的类中异常处理机制的改进(即PreparedStatement
,Resultset
)
You might also find this question interesting: Closing ResultSet in Java 7
您可能还会发现这个问题很有趣:Closing ResultSet in Java 7