虽然Connection之后关闭,但必须单独关闭JDBC结果集和语句吗?

Zee*_*mee 245 java jdbc

据说在使用后关闭所有JDBC资源是一个好习惯.但是,如果我有以下代码,是否有必要关闭Resultset和Statement?

Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
    conn = // Retrieve connection
    stmt = conn.prepareStatement(// Some SQL);
    rs = stmt.executeQuery();
} catch(Exception e) {
    // Error Handling
} finally {
    try { if (rs != null) rs.close(); } catch (Exception e) {};
    try { if (stmt != null) stmt.close(); } catch (Exception e) {};
    try { if (conn != null) conn.close(); } catch (Exception e) {};
}
Run Code Online (Sandbox Code Playgroud)

问题是连接的关闭是否完成了工作,或者是否使用了一些资源.

Pau*_*aul 191

你所做的是完美和非常好的练习.

我说它的良好实践的原因...例如,如果由于某种原因你使用"原始"类型的数据库池并且你调用connection.close(),连接将返回到池并且ResultSet/ Statement将永远不会被关闭然后你会遇到很多不同的新问题!

所以你不能总是指望connection.close()清理.

我希望这有帮助 :)

  • @Paul - 有趣.这听起来像是JDBC驱动程序的缺点. (7认同)
  • ......以及明确关闭一切的最明显的理由. (4认同)
  • @Ralph Stevens - 你不能指望这一点.我遇到过MSSQL JDBC驱动程序泄漏内存的情况,因为即使在收集垃圾后,ResultSet也没有关闭. (3认同)
  • 我同意关闭结果集和语句是一种好习惯.但是,结果集和语句是垃圾收集的 - 它们不会永远保持打开状态,并且不会"遇到许多不同的新问题". (2认同)
  • @tleb - 这将按预期工作.虽然从理论上讲,例外是"昂贵的",所以会有一个非常小的性能爆震(你已经确定) (2认同)

Raú*_*udo 114

借助try-with-resources语句, Java 1.7让我们的生活更加轻松.

try (Connection connection = dataSource.getConnection();
    Statement statement = connection.createStatement()) {
    try (ResultSet resultSet = statement.executeQuery("some query")) {
        // Do stuff with the result set.
    }
    try (ResultSet resultSet = statement.executeQuery("some query")) {
        // Do more stuff with the second result set.
    }
}
Run Code Online (Sandbox Code Playgroud)

这种语法非常简洁和优雅.connection即使statement无法创建,也会被关闭.

  • 你不需要像这样嵌套,你可以在一个try-with-resources中完成所有操作,只需将资源声明视为单独的语句(用`;`分隔) (54认同)
  • Mark Rotteveel:您可以对所有三个Connection,Statement和ResultSet使用单个尝试,但是如果要执行多个查询,则必须在开始新查询之前关闭先前的ResultSet.至少这就是我使用的DBMS的工作方式. (2认同)

dog*_*ane 69

来自javadocs:

关闭Statement对象时,其当前ResultSet对象(如果存在)也将关闭.

然而,的Javadoc不是是否很清晰Statement,并ResultSet在关闭底层被关闭Connection.他们只是声明关闭连接:

立即释放此Connection对象的数据库和JDBC资源,而不是等待它们自动释放.

在我看来,总是明确地关闭ResultSets,StatementsConnections当你与他们完成作为实现的close可能数据库驱动程序之间变化.

您可以通过使用诸如节省大量的锅炉板代码closeQuietlyDBUtils Apache的.

  • 谢谢狗巴恩。关键是你不能依赖 Connection.close 的实现,对吧? (2认同)

小智 37

我现在正在使用Oracle和Java.在这里我的观点:

您应该关闭ResultSetStatement明确表示,因为Oracle在关闭连接后仍保持游标保持打开状态.如果不关闭ResultSet(光标),则会抛出超出最大打开游标的错误.

我想您可能会遇到与您使用的其他数据库相同的问题.

完成后,这是教程Close ResultSet:

完成后关闭ResultSet

ResultSet一旦完成ResultSet对象的处理就关闭对象,即使Statement对象在关闭ResultSet时隐式关闭 对象,ResultSet显式关闭ResultSet也会让垃圾收集器尽可能早地重新收集内存,因为对象可能会占用大量内存,具体取决于查询.

ResultSet.close();


bar*_*on5 7

如果你想要更紧凑的代码,我建议使用Apache Commons DbUtils.在这种情况下:

Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
    conn = // Retrieve connection
    stmt = conn.prepareStatement(// Some SQL);
    rs = stmt.executeQuery();
} catch(Exception e) {
    // Error Handling
} finally {
    DbUtils.closeQuietly(rs);
    DbUtils.closeQuietly(stmt);
    DbUtils.closeQuietly(conn);
}
Run Code Online (Sandbox Code Playgroud)

  • 如果我使用此代码而不是rs.close(),stmt.close(),conn.close()会发生什么 (2认同)

Ene*_*cio 5

不,您不需要关闭任何东西,但连接。每个 JDBC 规范关闭任何更高的对象将自动关闭更低的对象。ClosingConnection将关闭Statement连接创建的任何s。关闭 anyStatement将关闭ResultSet由 that 创建的所有s Statement。是否Connection可池化无关紧要。即使是可池连接也必须在返回池之前清理。

当然,您可能在Connection创建大量语句时有很长的嵌套循环,然后关闭它们是合适的。我几乎从不关闭ResultSet,关闭StatementConnection将关闭它们时似乎过度。