在哪里关闭java的PreparedStatements和ResultSets?
考虑一下代码:
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();
}
上面的代码无法编译,因为 PreparedStatement.close()
和 ResultSet.close()
都会抛出 java.sql.SQLException
>。 那么我是否需要在finally子句中添加一个try/catch块呢? 或者将 close 语句移到 try 子句中? 或者只是懒得打电话关闭?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
在 Java 7 中,您不应显式关闭它们,而应使用自动资源管理< /a> 确保资源 已关闭并对异常情况进行适当处理。 异常处理的工作原理如下:
希望这是有道理的。 允许漂亮的代码,如下所示:
在 Java 7 之前,最好使用嵌套的 finally 块,而不是测试 null 引用。
我将展示的示例可能因深度嵌套而看起来很难看,但实际上,设计良好的代码可能不会用相同的方法创建连接、语句和结果; 通常,每个级别的嵌套都涉及将资源传递给另一个方法,该方法将其用作另一个资源的工厂。 通过这种方法,来自
close()
的异常将屏蔽try
块内部的异常。 这是可以克服的,但它会导致代码更加混乱,并且需要一个自定义异常类来提供 Java 7 中存在的“抑制”异常链。In Java 7, you should not close them explicitly, but use automatic resource management to ensure that resources are closed and exceptions are handled appropriately. Exception handling works like this:
Hopefully that makes sense. In allows pretty code, like this:
Prior to Java 7, it's best to use nested finally blocks, rather than testing references for 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 thetry
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.如果您真的手动编写自己的 jdbc,它肯定会变得混乱。 finally 中的 close() 需要用它自己的 try catch 包装,这至少是丑陋的。 您无法跳过关闭,尽管连接关闭时资源将被清除(如果您使用的是池,则可能不会立即清除)。 实际上,使用框架(例如 hibernate)来管理数据库访问的主要卖点之一是管理连接和结果集处理,这样您就不会忘记关闭。
您可以做一些像这样简单的事情,这至少可以隐藏混乱,并保证您不会忘记某些事情。
进而,
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.
You can do something simple like this, which at least hides the mess, and guarantees that you don't forget something.
and then,
对于文件 I/O,我通常在finally 块中添加一个try/catch。 但是,您必须小心,不要从finally块中抛出任何异常,因为它们将导致原始异常(如果有)丢失。
有关数据库连接关闭的更具体示例,请参阅本文。
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.
See this article for a more specific example of database connection closing.
另请注意:
“当关闭 Statement 对象时,其当前 ResultSet 对象(如果存在)也将被关闭。”
http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Statement.html#close()< /a>
仅在finally 中关闭PreparedStatement 就足够了,并且仅当它尚未关闭时才关闭。 如果您想真正特别,请首先关闭 ResultSet,而不是在关闭PreparedStatement之后(之后关闭它,就像这里的一些示例一样,实际上应该保证出现异常,因为它已经关闭了)。
Also note:
"When a Statement object is closed, its current ResultSet object, if one exists, is also closed. "
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).
不要浪费时间编写低级异常管理代码,而是使用 Spring-JDBC 等更高级别的 API,或者连接/语句/rs 对象的自定义包装器,来隐藏混乱的 try-catch 代码。
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.
基于 @erickson 的答案,为什么不像这样在一个
try
块中执行此操作呢?请注意,您不需要在
try
块内创建ResultSet
对象,因为当PreparedStatement 执行时
对象已关闭。ResultSet
会自动关闭参考: https://docs.oracle.com/javase /7/docs/api/java/sql/ResultSet.html
Building on @erickson's answer, why not just do it in one
try
block like this?Note that you don't need to create the
ResultSet
object inside thetry
block asResultSet
's are automatically closed when thePreparedStatement
object is closed.Reference: https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
我通常有一个实用程序方法可以关闭这样的事情,包括注意不要尝试使用空引用执行任何操作。
通常,如果
close()
抛出异常,我实际上并不关心,所以我只是记录异常并吞下它 - 但另一种选择是将其转换为RuntimeException
。 无论哪种方式,我建议使用易于调用的实用方法来执行此操作,因为您可能需要在很多地方执行此操作。请注意,如果关闭PreparedStatement失败,您当前的解决方案将不会关闭ResultSet - 最好使用嵌套的finally块。
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 aRuntimeException
. 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.Note that your current solution won't close the ResultSet if closing the PreparedStatement fails - it's better to use nested finally blocks.
如果您使用的是 Java 7,则可以使用那些实现 AutoCloseable (即
PreparedStatement
、Resultset
)您可能还会发现这个问题很有趣:在 Java 7 中关闭结果集
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
)You might also find this question interesting: Closing ResultSet in Java 7
我知道这是一个老问题,但为了以防万一有人正在寻找答案,java 现在有了 try-with-resouce 解决方案。
I know this is an old question, but just in case someone is looking for the answer, java now has the try-with-resouce solution.
不要省略调用 close。 这可能会导致问题。
我更喜欢在finally 中添加try/catch 块。
Do no omit calling close. It may cause problems.
I prefer adding try/catch block to the finally.
重点是finally子句,
我觉得你要修改2点。
首先,使用 try & 在 fainlly 子句中再次捕获。
其次,在执行 ps.close() 之前执行 rs.close()。
[电子邮件受保护]
focus finally clause,
I think you have to modify 2 points.
First, use try & catch again in fainlly clause.
Second, do rs.close() before doing ps.close().
[email protected]
可能是一种古老的(虽然简单)的做事方式,但它仍然有效:
Probably an old (though simple) way to do things, but it still works:
我用这个..
I use this..