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。

看到:

对JDBC以及任何实现AutoCloseable的资源使用try-with-resources。

您可以在try( … )中放置一个或多个资源。与分号分开,最后一个分号是可选的。 Java将跟踪资源,每个资源都以打开的相反顺序关闭。如果中间发生异常,Java知道不会尝试关闭空资源对象。这大大简化了您的编码。

以上是关于Java ResultSet未正确关闭的主要内容,如果未能解决你的问题,请参考以下文章

什么是关闭 ResultSet 的正确时间

如何避免 ResultSet 是 Java 中的关闭异常?

从 ResultSet Java 中获取价值 [关闭]

ResultSet 没有正确定位,可能需要在 java 中调用 next

java.sql.SQLException: 关闭的 Resultset: next

java.sql.SQLException:ResultSet关闭后不允许操作[重复]