опережающие часы с отметками времени Oracle на Java 10 - PullRequest
0 голосов
/ 05 июня 2018

У нас есть приложение, в котором есть модульные тесты с использованием H2 и интеграционные тесты с использованием Oracle 11. Все тесты проходили с использованием Java 8. У нас есть таблица Foo с отметкой времени created_at с использованием SQL DDL created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL, котораямы используем как Oracle, так и H2 в режиме Oracle.

Создать Foo просто.Мы создаем метку времени в Java:

final Instant createdAt = Instant.now();

Затем у нас есть SQL для вставки новой строки 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));

Следует помнить одну вещь: когда мы помещаем Foo в базу данных, мы больше не запрашиваем значение;мы возвращаем Foo объект, используя переданную нам Java Instant, предполагая, что он такой же, как в базе данных (потому что мы только что вставили его).

У нас есть другой запрос для чтения значения избаза данных.Во время запроса мы получаем значение из результирующего набора, например:

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

Ничего загадочного, насколько я вижу,

Мы обновились с Java 8 до Java 10. Внезапно нашмодульные тесты провалились с H2.Может показаться (если я не ошибаюсь), что Java теперь поддерживает микросекундную точность в Instant, но H2 должен был хранить значения с точностью до миллисекунды, поэтому наши утверждения не будут соответствовать тому, что мы получили обратно;один будет иметь 000 для микросекунд.(См. H2 Issue # 1178 .) Итак, мы решили, что мое усечение до миллисекунд:

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

С нашими модульными тестами, работающими на H2, мы выполнили те же тесты, что и интеграционные тесты наОракул:

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

Подождите, что?Временная метка для foo, которую мы получили , была на одну миллисекунду позже , чем время создания?Как это возможно?Мы обрезали до миллисекунд.Даже если Instant в Java 10 обладает большей точностью, чем хранит Oracle, мы отбросили все за миллисекунды.Как хранилище меток времени Oracle получает впереди оригинальной метки времени Instant?

...