与内存数据库中的相同H2建立多个连接

时间:2018-04-19 12:58:03

标签: java unit-testing jdbc h2

我经常遇到同样的问题:我想使用内存数据库对DAO进行单元测试。我正在使用H2,但我相信问题与HSQLDB几乎相同。我的单元测试涉及三个步骤:

  • 创建数据库和设置数据库模式(例如,使用SQL脚本)
  • 在数据库中插入测试所需的数据(例如:使用DbUnit)
  • 执行实际测试

在非常简单的情况下,可以对所有三个步骤使用相同的连接,但只要事情变得复杂一些(例如,当使用框架查询数据库而不是使用直接的PreparedStatements时),每步需要一个连接。

问题:一旦连接关闭,数据库似乎就会被删除。怎么解决?

1 个答案:

答案 0 :(得分:3)

关于这个主题,H2 documentation给出了两个提示:

  

有时与同一内存数据库有多个连接   需要。在这种情况下,数据库URL必须包含名称。例:   jdbc:h2:mem:db1。使用此URL访问同一数据库仅起作用   在同一个虚拟机和类加载器环境中。

     

默认情况下,关闭与数据库的最后一个连接会关闭   数据库。对于内存数据库,这意味着内容丢失。   要使数据库保持打开状态,请将;DB_CLOSE_DELAY=-1添加到数据库中   URL。只要保留内存数据库的内容   虚拟机处于活动状态,请使用jdbc:h2:mem:test;DB_CLOSE_DELAY=-1

所以第一个解决方案是将;DB_CLOSE_DELAY=-1添加到h2 url。但我对它有点不满意,因为它说数据库将永远保留在内存中,而我希望它只在我的测试运行时才能存在。

有关DB_CLOSE_DELAY的文档提供了更多信息:

  

设置关闭所有连接时关闭数据库的延迟。值-1表示在关闭延迟设置为某个其他值或调用SHUTDOWN之前,数据库永远不会关闭。值0表示没有延迟(默认值;如果数据库的最后一个连接已关闭,则数据库将关闭)。值1和更大值表示关闭最后一个连接后数据库保持打开的秒数。

它提示其他解决方案,例如在关机前稍微延迟或手动调用SHUTDOWN(我还没有找到如何在内存数据库中使用)。

最后,我将如何对其进行排序:由于数据库在 last 连接关闭时关闭,因此我将在创建时保持打开空白连接数据库,直到我不再需要它为止。这个解决方法有点hacky(只保留一个备用连接以保持数据库存活基本上是一种浪费),但它是迄今为止我发现的最优雅的解决方案。这是一个非常简化的抽象单元测试类片段,用于说明此解决方案:

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对象初始化用于查询数据库的库,以及执行问题中列出的其他两个步骤。测试完成后,空白连接将关闭,内存数据库也将关闭。

相关问题