Java中JDBC利用try-with-resources自动释放数据库连接,核心在于Connection、Statement、ResultSet必须在try()内直接声明初始化且实现AutoCloseable接口(JDBC 4.0+/Java 7+已支持);资源按声明逆序关闭(ResultSet→Statement→Connection),需确保驱动版本(如MySQL 8.0+)和JDK≥7,连接池环境下安全但@Transactional中close会被拦截。

Java 中 JDBC 利用 try-with-resources 自动释放数据库连接,核心在于让 Connection、Statement(或 PreparedStatement)、ResultSet 这些对象在 try 括号内直接声明并初始化,且它们必须实现 AutoCloseable 接口——而从 JDBC 4.0(对应 Java 7+)起,这些接口已天然支持。
资源必须在 try() 中声明并初始化
只有写在 try 小括号里的资源,才会被 JVM 自动识别和管理。不能先声明变量再赋值,否则 close() 不会触发。
- ✅ 正确:
try (Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.prepareStatement("...")) { ... } - ❌ 错误:
Connection conn; try { conn = ...; } finally { conn.close(); }—— 这是传统写法,不享受自动关闭
多个资源要一起声明,按依赖关系逆序写
JDBC 资源有明确依赖:ResultSet ← Statement ← Connection。try-with-resources 按声明顺序的逆序关闭(后声明的先关),正好符合释放逻辑,避免“连接已关、结果集还在读”的异常。
- 推荐顺序:
Connection → Statement → ResultSet - 示例:
try (Connection c = ds.getConnection(); PreparedStatement s = c.prepareStatement(sql); ResultSet rs = s.executeQuery()) { ... } - 编译器会确保执行顺序为:
rs.close() → s.close() → c.close()
驱动和 JDK 版本不能太旧
如果编译报错 “cannot be auto-closed”,大概率是 JDBC 驱动版本过低:
立即学习“Java免费学习笔记(深入)”;
- MySQL:需使用 Connector/J 8.0+(5.1.x 不支持 AutoCloseable)
- PostgreSQL:需 42.2.0+(对应 JDBC 4.2)
- JDK 必须 ≥ 7,且项目编译目标(source/target)设为 1.7 或更高
- 验证方式:
System.out.println(Driver.class.getPackage().getImplementationVersion());
连接池环境下也安全,但要注意事务上下文
用 HikariCP、Druid 等连接池时,close() 实际是归还连接而非销毁物理连接,所以 try-with-resources 完全适用。
- ✅ 安全:Spring 管理的连接池 + 非事务方法中,
close()就是归还 - ⚠️ 注意:
@Transactional方法内获取的 Connection 是代理对象,close()会被 Spring 拦截忽略,由事务管理器统一控制生命周期 - ❌ 禁止:在 try-with-resources 外再手动调用
conn.close(),可能抛出 “connection is closed” 异常


















