内存数据库中的 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”