我有一个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()行。但是结果集实际上并没有关闭。
我添加了一个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");
}
}
}
输出:
test1
test2
test3
我的问题是,为什么需要将rs.close()和stmt.close()称为两次? try
子句中的调用似乎无效。但是,我在finally
子句中再次调用了它们,它们成功了。这怎么可能?
答案 0 :(得分:1)
使用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");
}
答案 1 :(得分:0)
否,JDBC不需要两次调用close
。我怀疑还有其他事情发生。
我们不能确定地确定您的代码中发生了什么。我们不知道您所谓的第二通电话是否确实解决了该问题。例如,Statement::close
的文档说:
在已关闭的Statement对象上调用close方法无效。
正如Answer by Andreas所建议的那样,您应该使用try-with-resources。
请参阅:
将try-with-resources用于JDBC以及实现AutoCloseable
的任何资源。
您可以在您的try( … )
中放入一个或多个资源。用分号分隔,最后一个分号是可选的。 Java将跟踪资源,每个资源以打开的相反顺序关闭。如果中间发生异常,则Java不会尝试关闭空资源对象。这样可以大大简化您的编码。