Java 7+ 的 JDBC 资源(Connection、Statement 及其子类、ResultSet)均实现 AutoCloseable,支持 try-with-resources 自动关闭;按创建逆序关闭,确保依赖关系正确,避免泄漏。

Java 中使用 JDBC 时,Connection、Statement、ResultSet 这些资源必须显式关闭,否则容易造成连接泄漏、内存占用升高甚至数据库连接池耗尽。从 Java 7 开始,try-with-resources 语句提供了自动资源管理机制,只要资源实现了 AutoCloseable 接口(JDBC 4.0+ 的所有核心接口都已实现),就能在 try 块结束时自动调用 close(),无需手动写 finally 块。
哪些 JDBC 资源支持 try-with-resources
以下类/接口均实现了 AutoCloseable,可直接用于 try-with-resources:
java.sql.Connection-
java.sql.Statement(含PreparedStatement、CallableStatement) java.sql.ResultSet
标准写法:嵌套声明,按依赖顺序逆序关闭
资源按“创建顺序的反序”自动关闭(即先打开的后关闭),这符合 JDBC 资源依赖关系(ResultSet 依赖 Statement,Statement 依赖 Connection)。推荐在一个 try 括号内声明全部资源:
try (Connection conn = DriverManager.getConnection(url, user, pwd);
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE id = ?");
ResultSet rs = stmt.executeQuery()) {
<pre class="brush:php;toolbar:false;">stmt.setInt(1, 123);
while (rs.next()) {
System.out.println(rs.getString("name"));
}} catch (SQLException e) { // 处理异常 }
上面代码中,rs.close() → stmt.close() → conn.close() 会自动执行,即使循环中抛出异常或提前 return,也保证关闭。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
立即学习“Java免费学习笔记(深入)”;
注意事项和常见误区
-
不要在 try 内部重新赋值资源变量:如
stmt = conn.prepareStatement(...)会破坏自动关闭逻辑,应确保每个资源只被声明并初始化一次。 -
异常抑制(Suppressed Exception):如果 try 块抛出异常,且 close() 也抛出异常,后者会被“抑制”,可通过
ex.getSuppressed()获取;通常只需关注主异常。 -
不建议混合使用 try-with-resources 和手动 close:比如在 try 内再调用
rs.close(),会导致重复关闭(可能抛出异常)。 -
Connection 来自连接池时仍需关闭:调用
close()实际是归还连接,不是销毁物理连接,所以必须关闭,否则连接永远不归还。
更安全的实战示例(含参数化与异常处理)
真实项目中常结合连接池(如 HikariCP)和预编译语句:
String sql = "INSERT INTO logs (level, message, created_at) VALUES (?, ?, ?)";
try (Connection conn = dataSource.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
<pre class="brush:php;toolbar:false;">stmt.setString(1, "INFO");
stmt.setString(2, "User login succeeded");
stmt.setTimestamp(3, Timestamp.from(Instant.now()));
stmt.executeUpdate();} catch (SQLTimeoutException e) { // 超时专用处理 } catch (SQLException e) { // 其他 SQL 异常 }
这里没有 ResultSet,但 Connection 和 PreparedStatement 依然被自动释放,简洁又可靠。

















