Java 10上带有Oracle时间戳的跳转时钟

时间:2018-06-05 15:29:28

标签: java sql oracle h2 java-time

我们有一个应用程序,它使用H2进行单元测试,使用Oracle 11进行集成测试。所有测试都使用Java 8进行传递。我们有一个Foo表,使用SQL DDL created_at时间戳{ {1}},我们在Oracle模式下使用Oracle和H2。

创建created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL很简单。我们在Java中创建一个时间戳:

Foo

然后我们使用SQL在表中插入一个新的final Instant createdAt = Instant.now(); 行,使用时间戳和其他东西:

Foo

(我们执行小INSERT INTO Foo (uuid, name, created_at, bar_id) SELECT ?, ?, ?, id FROM Bar WHERE Bar.name = ?; 技巧以确保我们按名称查找匹配的SELECT,但这与时间戳无关。)

在预备语句中填写时间戳很简单:

Bar

需要注意的一点是,当我们将preparedStatement.setTimestamp(3, Timestamp.from(createdAt)); 放入数据库时​​,我们不会再次查询该值;我们使用传递给我们的Java Foo返回一个Foo对象,假设它与数据库中的相同(因为我们只是插入它)。

我们有另一个查询来从数据库中读取值。在查询期间,我们从结果集中获取值,如下所示:

Instant

从我所看到的,没有什么神秘的。

我们从Java 8升级到Java 10.突然间,我们的单元测试因H2而失败。它会出现(除非我错了)Java now supports microsecond precision in Instant,但H2必须以毫秒精度存储值,因此我们的断言与我们得到的断言不匹配;一个人将有return Timestamp.toInstant(resultSet.getTimestamp("created_at")); 微秒。 (参见H2 Issue #1178。)所以我们解决了截断到毫秒的问题:

000

我们的单元测试用于H2,我们运行与Oracle上的集成测试相同的测试:

assertThat(retrievedFoo.getCreatedAt().truncatedTo(MILLIS),
    is(createdFoo.getCreatedAt().truncatedTo(MILLIS)));
等等,什么?我们检索的foo上的时间戳比创建时间 1毫秒怎么可能?我们截断到毫秒。即使Java 10上的Expected: is <2018-06-05T14:32:32.111Z> but: was <2018-06-05T14:32:32.112Z> 比Oracle存储的精度更高,我们也会在毫秒之后丢弃所有内容。 Oracle的时间戳存储如何提前提前原始时间戳Instant

0 个答案:

没有答案