必须按 ResultSet → Statement 顺序显式关闭资源,优先使用 try-with-resources 自动管理;Connection.close() 不保证级联关闭,不可依赖。

正确释放 ResultSet 和 Statement 资源,关键在关闭顺序、方式和时机——不是“关了就行”,而是“谁先关、怎么关、在哪关”都影响资源是否真正释放、会不会报错或泄漏。
必须按 ResultSet → Statement 顺序关闭
ResultSet 依赖 Statement,Statement 又依赖 Connection。如果 Statement 先关,ResultSet 再调用 next()、getString() 等方法,会直接抛出 “Statement closed” 异常;若 Connection 先关,Statement 和 ResultSet 更无法使用。
- ✅ 正确顺序:rs.close() → stmt.close()
- ❌ 错误做法:stmt.close() 在 rs 处理完之前就执行;或把 rs.close() 放在 finally 外、甚至完全省略
- 注意:即使用了连接池,ResultSet 和 Statement 仍需显式关闭——连接池只管理 Connection 的复用,不替你关 Statement 或 ResultSet
优先用 try-with-resources 自动管理
JDBC 4.0+(如 ojdbc8、mysql-connector-java 8.x)中,ResultSet 和 Statement 都实现了 AutoCloseable,天然支持 try-with-resources。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 资源必须在 try( ) 括号内声明并初始化,例如:
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM user")) {
// 处理数据
} - JVM 自动按声明的逆序关闭:rs 先关,stmt 后关,顺序天然合规
- 即使执行中抛异常,close() 仍会触发;若 close 本身也出错,会被抑制,主异常仍向上抛出
传统 finally 方式要严守三原则
兼容老项目或需捕获关闭异常时,可用 try-catch-finally,但必须做到:
立即学习“Java免费学习笔记(深入)”;
- 变量提前声明为 null:
ResultSet rs = null;
Statement stmt = null; - 每个 close() 单独判空 + 单独 try-catch:
if (rs != null) { try { rs.close(); } catch (SQLException e) { /* 记日志 */ } }
if (stmt != null) { try { stmt.close(); } catch (SQLException e) { /* 记日志 */ } } - finally 块里不 return、不 throw,否则可能掩盖原始业务异常
别指望 Connection.close() 帮你兜底
有些驱动文档提到 Connection.close() 会级联关闭它创建的所有 Statement/ResultSet,但这不是 JDBC 规范强制行为,不同驱动表现不一。
- ojdbc6 对部分场景可能自动关,ojdbc8 已明确不保证
- MySQL Connector/J 8.x 默认不自动关闭,必须手动或用 try-with-resources
- 依赖这个行为 = 埋雷:换驱动、升级版本后可能突然出现连接泄漏或“ResultSet closed”异常

















