正确关闭JDBC资源必须按ResultSet→Statement→Connection顺序,推荐try-with-resources自动逆序关闭;旧版用finally手动判空关闭,严禁反序或省略。

正确关闭 JDBC 资源的核心就一条:**谁先创建、谁后关;谁依赖谁,就谁先关**。ResultSet 依赖 Statement,Statement 依赖 Connection,所以必须按 ResultSet → Statement → Connection 的顺序关闭,否则可能报“Connection closed”或静默泄漏。
推荐用 try-with-resources(Java 7+)
这是最简洁、最安全的方式,JVM 自动按逆序调用 close(),且异常处理健壮:
- 资源必须在
try()括号内声明并初始化,例如:try (Connection c = ds.getConnection(); PreparedStatement ps = c.prepareStatement(sql); ResultSet rs = ps.executeQuery()) { ... } - 关闭顺序自动为
rs.close() → ps.close() → c.close(),天然符合依赖逻辑 - 即使执行中抛 SQLException,close() 仍会执行;若 close 过程也出错(如网络断连),异常会被抑制(suppressed),主异常仍向上抛,可用
e.getSuppressed()查看 - 不支持该语法的老项目(如 Java 6 及以下)请改用传统方式
传统 try-catch-finally 手动关闭(兼容旧环境)
适用于无法升级 JDK 或需精细控制的场景,但必须严守三要素:
- 变量提前声明为 null:Connection conn = null; PreparedStatement ps = null; ResultSet rs = null;
-
每个 close() 独立判空 + 独立 try-catch:
不能把三个 close 塞进同一个 try 块——一个失败就会中断后续释放
例如:if (rs != null) try { rs.close(); } catch (SQLException e) { /* 记录日志,不抛出 */ } - finally 中不 return、不 throw:避免吞掉原始 SQL 异常,影响问题定位
别踩这些常见坑
看似省事,实则埋雷:
立即学习“Java免费学习笔记(深入)”;
- 只关 Connection,指望它自动级联关闭其他资源——不可靠。不同驱动行为不一致,ResultSet 和 Statement 的底层资源(如游标、内存缓冲)未必被及时释放
- 在 finally 里用单个 try 块关全部资源——
rs.close()抛异常后,ps.close()和c.close()就不会执行 - 先 close Connection 再 close ResultSet——直接抛异常,因为 ResultSet 依赖活跃连接
- ResultSet 声明在 try 外部、再赋值——JVM 不识别为受管资源,try-with-resources 不生效
小提醒:连接池环境下也要关
用 HikariCP、Druid 等连接池时,conn.close() 实际是归还连接而非物理断开,但依然必须调用。不调用会导致连接永远不归还,池很快耗尽。Statement 和 ResultSet 同理——池管理的是 Connection,不替你管 Statement 或 ResultSet 的生命周期。



















