必须按 ResultSet → Statement → Connection 顺序关闭,且需确保异常时仍执行;推荐用 try-with-resources 自动逆序关闭,兼容旧版则在 finally 中逐个判空并捕获异常关闭。

在 Java 中正确关闭 Connection、Statement 和 ResultSet 的关键是:按**相反顺序关闭**,并确保**无论是否异常都执行关闭操作**。最稳妥的方式是使用 try-with-resources 语句,它会自动调用 close() 方法,避免资源泄漏。
为什么必须按 ResultSet → Statement → Connection 顺序关闭
这三个对象存在依赖关系:ResultSet 依赖 Statement,Statement 又依赖 Connection。如果先关闭 Connection,再尝试读取 ResultSet(比如在 finally 块中),会抛出异常或返回空结果;提前关闭 Statement 也可能使关联的 ResultSet 失效。所以关闭顺序必须是:先关 ResultSet,再关 Statement,最后关 Connection。
推荐方式:用 try-with-resources 自动管理
Java 7+ 引入的 try-with-resources 是最简洁安全的做法。只要这些对象实现了 AutoCloseable 接口(JDBC 4.0+ 的所有标准实现都满足),就能自动关闭:
// 示例:查询并安全释放资源
String sql = "SELECT id, name FROM users WHERE age > ?";
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
<pre class="brush:php;toolbar:false;">stmt.setInt(1, 18);
while (rs.next()) {
System.out.println(rs.getInt("id") + ": " + rs.getString("name"));
}
// 离开 try 块时,rs、stmt、conn 会按逆序自动 close()
} catch (SQLException e) { // 处理异常 }
注意:多个资源用分号分隔,它们会按声明的**逆序**关闭(即 rs → stmt → conn),完全符合要求。
兼容旧版本或需手动控制时的 finally 关闭写法
若无法使用 try-with-resources(如 JDK 6 或特殊场景),应在 finally 块中逐个关闭,并对每个 close() 调用做非空判断和异常捕获:
- 检查对象是否为
null,避免NullPointerException - 每个
close()单独 try-catch,防止前一个关闭异常影响后续关闭 - 不把
close()放在 try 块里,否则异常可能掩盖原始业务异常
// 手动关闭示例(不推荐,仅作兼容参考)
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = dataSource.getConnection();
stmt = conn.prepareStatement("SELECT * FROM users");
rs = stmt.executeQuery();
// 处理结果...
} catch (SQLException e) {
// 处理异常
} finally {
if (rs != null) {
try { rs.close(); } catch (SQLException ignored) {}
}
if (stmt != null) {
try { stmt.close(); } catch (SQLException ignored) {}
}
if (conn != null) {
try { conn.close(); } catch (SQLException ignored) {}
}
}
常见误区提醒
- 只关 Connection 就够了? 错。某些 JDBC 驱动不会自动关闭关联的 Statement/ResultSet,尤其在连接池环境下,可能导致游标泄漏或数据库连接数打满
- 在 try 块里 close()? 不安全。一旦前面语句抛异常,close() 可能不执行
-
用 Apache Commons DbUtils? 它的
DbUtils.closeQuietly()可简化手动关闭,但本质仍是封装了 null 检查和异常吞没,不如 try-with-resources 直观可靠
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











