代码之家  ›  专栏  ›  技术社区  ›  Garret Wilson

Java 10上带Oracle时间戳的提前时钟

  •  1
  • Garret Wilson  · 技术社区  · 7 年前

    我们有一个应用程序,它使用H2进行单元测试,使用Oracle 11进行集成测试。所有测试都通过了Java 8。我们有一个 Foo 有一个 created_at 使用SQL DDL的时间戳 created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL ,我们在Oracle上和在Oracle模式下的H2上都使用它。

    创建 很简单。我们用Java创建一个时间戳:

    final Instant createdAt = Instant.now();
    

    然后我们用SQL插入一个新的 使用时间戳和其他东西将行放入表中:

    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的对象 Instant 传递给我们,假设它与数据库中的相同(因为我们刚刚插入了它)。

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

    return Timestamp.toInstant(resultSet.getTimestamp("created_at"));
    

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

    我们从Java 8升级到Java 10。突然我们的单元测试因H2而失败。看起来(除非我错了)是 Java now supports microsecond precision in Instant ,但是H2必须以毫秒精度存储值,所以我们的断言与我们得到的结果不匹配;其中一个 000 微秒。(见H2 Issue #1178 )所以我们把截短到毫秒:

    assertThat(retrievedFoo.getCreatedAt().truncatedTo(MILLIS),
        is(createdFoo.getCreatedAt().truncatedTo(MILLIS)));
    

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

    Expected: is <2018-06-05T14:32:32.111Z>
         but: was <2018-06-05T14:32:32.112Z>
    

    等等,什么?foo上的时间戳我们 恢复 是一毫秒 后来 比创造的时间?怎么可能呢?我们缩短到毫秒。即使 瞬间 在Java 10上的精度比Oracle存储的要高,我们在几毫秒后就删除了所有内容。Oracle的时间戳存储是如何获得的 向前地 原始时间戳的 瞬间 ?

    0 回复  |  直到 7 年前