关于这个话题,H2 documentation 给出了两个提示:
有时到同一个内存数据库的多个连接是
必需的。在这种情况下,数据库 URL 必须包含名称。例子:
jdbc:h2:mem:db1。仅使用此 URL 访问同一数据库有效
在同一个虚拟机和类加载器环境中。
默认情况下,关闭与数据库的最后一个连接会关闭
数据库。对于内存数据库,这意味着内容丢失。
要保持数据库打开,请将;DB_CLOSE_DELAY=-1 添加到数据库
网址。保持内存数据库的内容只要
虚拟机还活着,使用jdbc:h2:mem:test;DB_CLOSE_DELAY=-1。
所以第一个解决方案是将;DB_CLOSE_DELAY=-1 添加到h2 url。但我对它有点不满意,因为它说数据库将永远留在内存中,而我希望它只在我的测试运行时才存在。
关于DB_CLOSE_DELAY 的文档提供了更多信息:
如果所有连接都关闭,则设置关闭数据库的延迟。值 -1 表示数据库永远不会关闭,直到关闭延迟设置为其他值或调用 SHUTDOWN。值 0 表示无延迟(默认值;如果与数据库的最后一个连接已关闭,则数据库将关闭)。值 1 和更大的值表示关闭最后一个连接后数据库保持打开状态的秒数。
它提示其他解决方案,例如在关机前稍微延迟或手动调用SHUTDOWN(我还没有找到如何在内存数据库上使用它)。
最后是我的整理方法:由于数据库在 last 连接关闭时关闭,我将只保持打开一个 blank 连接 从我创建的那一刻起数据库,直到我不再需要它为止。这种解决方法有点老套(让备用连接打开只是为了让数据库保持活动状态基本上是一种浪费),但它是迄今为止我找到的最优雅的解决方案。这是一个非常简化的抽象单元测试类的 sn-p 来说明这个解决方案:
import org.h2.jdbcx.JdbcDataSource;
public abstract class AbstractTestDao {
private Connection blankConnection;
private DataSource dataSource;
protected DataSource getDataSource() {
return dataSource;
}
@Before
public void setup() throws SQLException {
JdbcDataSource jdbcDataSource = new JdbcDataSource();
jdbcDataSource.setUrl("jdbc:h2:mem:test");
this.dataSource = jdbcDataSource;
this.blankConnection = dataSource.getConnection();
}
@After
public void tearDown() throws SQLException {
this.blankConnection.close();
}
}
儿童单元测试类将继承这一类并使用提供的 DataSource 对象来初始化用于查询数据库的库,以及执行问题中列出的其他两个步骤。测试完成后,空白连接关闭,内存数据库也关闭。