Java ResultSet未正确关闭
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java ResultSet未正确关闭相关的知识,希望对你有一定的参考价值。
我有一个包含许多代码片段的Java应用程序,如下例所示。非常简单地查询Oracle数据库。返回并解析有效数据,然后调用close()函数。
ResultSet rs = null;
Statement stmt = null;
try
{
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT * FROM example");
while (rs.next())
{
// do stuff
}
rs.close();
stmt.close();
System.out.println("test1");
}
catch (Exception e)
{
System.out.println("error1");
}
我开始遇到“超出最大游标数”错误。我检查了我的方法以确定ResultSet是否未被关闭。从未触发过catch
条款,并且每次都打印“test1”。这意味着不会跳过rs.close()和stmt.close()行。然而,ResultSet实际上并没有被关闭。
我添加了一个finally
条款,它解决了这个问题。
finally
{
if (rs != null)
{
try
{
rs.close();
System.out.println("test2");
}
catch (Exception e)
{
System.out.println("error2");
}
}
if (stmt != null)
{
try
{
stmt.close();
System.out.println("test3");
}
catch (Exception e)
{
System.out.println("error3");
}
}
}
OUTPUT:
test1
test2
test3
我的问题是,为什么rs.close()和stmt.close()需要被调用两次? try
条款中的调用似乎什么都不做。然而我在finally
条款中再次称呼它们,并且它们是成功的。这怎么可能?
使用try-with-resources(Java 7+):
try (Statement stmt = conn.createStatement()) {
try (ResultSet rs = stmt.executeQuery("SELECT * FROM example")) {
while (rs.next()) {
// do stuff
}
System.out.println("test1");
}
} catch (Exception e) {
System.out.println("error1");
}
No, no need to call twice
不,JDBC中没有必要两次调用close
。我怀疑还有其他事情发生了。
我们无法确定您的代码中发生了什么。我们无法知道您所谓的第二次通话是否确实解决了问题。例如,Statement::close
的文档说:
在已关闭的Statement对象上调用close方法无效。
try-with-resources
正如Answer by Andreas建议的那样,你应该使用try-with-resources。
看到:
- Java 7 tech note尝试使用资源。
- Oracle Tutorial。
- Java 9 enhancement使用Try-With-Resource Statement中的先前创建的变量来尝试资源。
对JDBC以及任何实现AutoCloseable
的资源使用try-with-resources。
您可以在try( … )
中放置一个或多个资源。与分号分开,最后一个分号是可选的。 Java将跟踪资源,每个资源都以打开的相反顺序关闭。如果中间发生异常,Java知道不会尝试关闭空资源对象。这大大简化了您的编码。
以上是关于Java ResultSet未正确关闭的主要内容,如果未能解决你的问题,请参考以下文章
ResultSet 没有正确定位,可能需要在 java 中调用 next