Java中try-with-resources可自动关闭H2/HSQLDB的Connection、Statement、ResultSet,前提是使用JDBC 4.1+驱动及兼容版本(H2≥1.4.192、HSQLDB≥2.3.4),资源按Connection→Statement→ResultSet顺序声明,JVM逆序调用close()确保安全释放。

Java 中 try-with-resources 可以自动释放 H2 或 HSQLDB 的数据库连接、Statement 和 ResultSet,前提是这些资源实现了 AutoCloseable 接口——而 JDBC 4.1+(JDK 7+)的 Connection、Statement、ResultSet 都已实现该接口,H2 和 HSQLDB 均完全支持。
确保使用 JDBC 4.1+ 驱动和兼容版本
H2(≥1.4.192)、HSQLDB(≥2.3.4)均提供符合 JDBC 4.1 规范的驱动,其返回的 Connection 等对象原生支持自动关闭。若使用旧版(如 H2 1.3.x),部分资源可能未正确实现 close() 或未声明 AutoCloseable,导致 try-with-resources 无效或静默失败。
- 检查 Maven 依赖是否为最新稳定版(例如 H2 使用
2.2.224,HSQLDB 使用2.7.2) - 避免混用 JDK 6 编译目标与 JDK 7+ 运行环境——编译时需设
source=7且target=7或更高 - 运行时确认 JVM 版本 ≥ Java 7(推荐 Java 8+)
正确写法:按资源获取顺序声明,嵌套也无需额外 try
Connection → Statement → ResultSet 是典型依赖链,应按“从外到内”顺序声明在 try 括号中,JVM 会逆序调用 close(),确保子资源先关闭、父资源后关闭,避免因父资源提前关闭导致子资源异常。
try (Connection conn = DriverManager.getConnection("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT 1")) {
while (rs.next()) {
System.out.println(rs.getInt(1));
}
} // 自动依次调用 rs.close() → stmt.close() → conn.close()
- 即使中间抛出异常(如 SQL 错误),所有已成功创建的资源仍会被逐个关闭
- 无需手动捕获 SQLException 来调用 close(),也不必写 finally 块
- 对 H2 内存库,
DB_CLOSE_DELAY=-1可防止连接关闭时立即销毁数据库,便于多连接测试
配合测试框架(JUnit 5)的安全用法
在单元测试中,常需复用内存数据库实例。此时不建议在每个 test 方法里反复建库关库,而是用 @BeforeAll 初始化连接池或 DataSource,再在每个 test 中用 try-with-resources 获取连接——既保证单次操作资源干净,又避免频繁启停 DB 开销。
立即学习“Java免费学习笔记(深入)”;
- H2 推荐使用
jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE - HSQLDB 对应使用
jdbc:hsqldb:mem:testdb;shutdown=true(注意:true 表示最后连接关闭时才销毁,不影响 try-with-resources) - 若使用 HikariCP / HikariDataSource,其
getConnection()返回的 Connection 仍支持 AutoCloseable,可直接用于 try-with-resources
常见陷阱与规避方式
不是所有“看起来像资源”的对象都适合放进 try-with-resources。例如:DataSource 本身不是资源,不能 close;某些自定义封装类若未正确委托 close(),也会导致泄漏。
- ❌ 错误:
try (DataSource ds = ...)—— DataSource 不是 AutoCloseable,且不应被关闭 - ❌ 错误:自己写的 DAO 工具类返回 Connection 但未包装成 try-safe,或 close() 方法为空实现
- ✅ 正确:只将
DriverManager.getConnection()、conn.createStatement()、stmt.executeQuery()的返回值放入 try 括号 - ✅ 调试技巧:在 H2 URL 加
;TRACE_LEVEL_SYSTEM_OUT=2,观察连接/语句的 open/close 日志


















