H2 数据库仅在文件中不能在内存中工作

eXt*_*eme 4 java spring hibernate h2

我有一个使用 Hibernate 设置的 Spring MVC 项目,并希望为某些服务创建一些测试。主应用程序使用 PostgreSQL 数据库,对于测试,我想在内存数据库中使用 H2

我为测试(Spring 和 Hibernate)创建了单独的配置文件,一切正常,直到我尝试访问内存数据库

休眠配置:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories("<repository>")
public class DataSourceTestConfig {

private static final Logger LOG = LogManager.getLogger(DataSourceTestConfig.class);

private static final String DATABASE_DRIVER = "org.h2.Driver";
//private static final String DATABASE_URL = "jdbc:h2:file:d:/test";
private static final String DATABASE_URL = "jdbc:h2:mem:test";
private static final String DATABASE_USERNAME = "sa";
private static final String DATABASE_PASSWORD = "";

private static final String HIBERNATE_DIALECT = "org.hibernate.dialect.H2Dialect";
private static final String HIBERNATE_SHOW_SQL = "true";
private static final String ENTITYMANAGER_PACKAGES_TO_SCAN = "<packages>";
private static final String HIBERNATE_HBM2DDL_AUTO = "create";
...
Run Code Online (Sandbox Code Playgroud)

问题似乎出在 DATABASE_URL 上:

如果我使用:

DATABASE_URL = "jdbc:h2:file:d:/test";
Run Code Online (Sandbox Code Playgroud)

一切都按预期工作。所有测试都按预期运行

如果我使用:

DATABASE_URL = "jdbc:h2:mem:test";
Run Code Online (Sandbox Code Playgroud)

所有的地狱都崩溃了,它不起作用:)

在这种情况下,我得到

 org.h2.jdbc.JdbcSQLException: Table "test" not found; SQL statement: ...
Run Code Online (Sandbox Code Playgroud)

查看 Hibernate 日志可以清楚地看到该表实际上是生成的:

 DEBUG org.hibernate.SQL - drop table test if exists
 ...
 DEBUG org.hibernate.SQL - create table test (<columns>)
 ...
 DEBUG org.hibernate.SQL - alter table test add constraint FKg74a38x6t762qifuge9cux03i foreign key ...
Run Code Online (Sandbox Code Playgroud)

等等 ...

在我看来,在这种情况下,数据库已生成,并且我正在以某种方式工作或在不同的实例上或发生某些事情,并且在创建和我的测试之间删除了表。

这些场景在我看来不太可能,因为没有 Hibernate 日志表明这一点(没有删除查询)测试日志在创建日志后立即开始

我在这里发现了类似的问题:H2 in-mem-DB with hibernate set to create give me table not found errors

但解决方案是使用文件。

这对我来说不是一个解决方案,因为这些测试必须在运行不同操作系统的许多机器上执行,所以硬编码的路径文件不是一个选项。此外,JDBC 不允许使用相对路径,因此我可以将数据库文件放在资源文件夹中。

有谁知道如何解决这个问题?

谢谢。

小智 6

我遇到了同样的问题并最终找到了解决方案:这是因为在数据库初始化后它又被关闭了。然而,在标准设置下,这会导致数据库被删除。当在您的测试中再次连接相同的 URL 时,您将拥有一个没有创建任何表的“新鲜”实例。

您可以通过在您的 JDBC URL 末尾附加“;DB_CLOSE_DELAY=-1”来防止数据库被关闭,例如

jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
Run Code Online (Sandbox Code Playgroud)

H2文档提供了这些设置的详细细节。