内存数据库中的 H2:使用 JDBC 设置时区? Java 单元测试

Posted

技术标签:

【中文标题】内存数据库中的 H2:使用 JDBC 设置时区? Java 单元测试【英文标题】:H2 In Memory DB: Set Timezone with JDBC? Java Unit Tests 【发布时间】:2018-10-12 20:44:09 【问题描述】:

我在使用 h2 时遇到了一个奇怪的困境。我们有一个内存中的 h2 db 设置,模式 a la Oracle,以帮助我们进行单元测试。 我们已将应用程序的时区设置为

@PostConstruct
void started() 
    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

我们在 maven/springboot 应用中将 h2 设置为数据源,如下所示:

datasource.config.url=jdbc:h2:mem:AZ;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=ORACLE;
datasource.config.username=sa
datasource.config.password=
datasource.config.driver-class-name=org.h2.Driver

我有一个基于时间戳的测试运行。所以我写了这个小映射器来从 h2 获取 DB 时间:

@Select("Select CURRENT_TIMESTAMP")
String selectCurrentTimestamp();

问题在于 h2 一直占用它运行的实际系统时间,而不是听上面列出的时区设置。因此,无论如何,我们的单元测试中的插入都会在正确的时间插入。但是基于时间的选择似乎会根据系统时间进行翻译,因此无法正常工作。我也已经过渡到使用 newer java 8 java.time 类作为我的选择函数等的参数。仍然没有骰子。

我已经阅读了很多关于这个问题的帖子,这些帖子涉及休眠(未明确使用)和其他一些稍微类似的问题。但是我还没有找到解决这个特定问题的方法,可以使用一些帮助。

谁是这个问题的真正根源,JDBC?还是H2?取决于此,我该如何开始修复它?是否有可以提供给 JDBC 连接 URL 的字符串?还是要进行其他设置?

【问题讨论】:

【参考方案1】:

我遇到了同样的问题。让我走上正确道路的提示来自this answer on a previous post:

请注意,加载驱动程序后,您无法更改时区。

在 Application 类中使用 PostConstruct 为时已晚。驱动加载后会设置时区默认值,H2 已经被锁定。

这里有几个可行的解决方案:

    提供一个 JVM 参数来设置时区:-Duser.timezone=UTC

    在加载 SpringApplication 之前(或在加载其他任何内容之前)设置时区默认值:

    public static void main(String[] args) 
       TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
       SpringApplication.run(Application.class, args);
    
    

    注意:您也可以在响应 ApplicationContextInitializedEvent 时运行它,因为尚未加载其他 bean。我不确定仅在 Main 中执行此操作是否有任何缺点。

【讨论】:

-Duser.timezone=UTC 这个选项也适用于 maven 测试 这解决了我们在使用时区进行测试时使用 Hibernate、ActiveMQ 和 JUnit 4 的问题。通过在我们启动 Hibernate 之前(或在调用 ActiveMQTestBase 构造函数之前)在 @BeforeClass 中调用 TimeZone.setDefault(),我们可以让 Hibernate 在时区进行单元测试。

以上是关于内存数据库中的 H2:使用 JDBC 设置时区? Java 单元测试的主要内容,如果未能解决你的问题,请参考以下文章

使用 JPA 和 JUnit 测试时如何一致地擦除内存数据库中的 H2 [重复]

org.h2.jdbc.JdbcSQLException:在使用 H2 数据库进行测试期间未找到列“Id”

如何使用 H2 内存数据库保存数据?

H2 和 Oracle 兼容性问题

为啥返回 org.h2.jdbc.JdbcSQLException?

org.h2.jdbc.JdbcSQLException:不支持的连接设置 AUTO_SERVER