Как настроить Hibernate6 по умолчанию для отметки времени с точностью до наносекунды?

Я хочу, чтобы Hibernate сохранял свойства LocalDateTime в базе данных H2 с точностью, содержащей наносекунды (Timestamp(9)) по умолчанию. «По умолчанию» означает, что прикрепление @Column(columnDefinition = "TIMESTAMP(9)") к каждому свойству LocalDateTime не может быть решением.

В Hibernate5 решением было создать собственный диалект и вызвать registerColumnType(Types.TIMESTAMP, "timestamp(9)") в его конструкторе.

Однако я не нашел решения для Hibernate6. Я попытался создать собственный диалект и переопределить его resolveSqlTypeLength.

public class CustomH2Dialect extends H2Dialect {


    /* The Hibernate 5 Solution was to call registerColumnType(Types.TIMESTAMP, "timestamp(9)"); in the ctor.*/ 
    @Override
    public int resolveSqlTypeLength(String columnTypeName, int jdbcTypeCode, int precision, int scale,
            int displaySize) {
        if (jdbcTypeCode == Types.TIMESTAMP) {
            return 9;
        }        
        
        return super.resolveSqlTypeLength(columnTypeName, jdbcTypeCode, precision, scale, displaySize);
    }
}

Но похоже, что метод не вызывается.

Есть ли у кого-нибудь идеи: как настроить TIMESTAMP(9) для всех временных меток (LocalDateTime...) по умолчанию? Репозиторий Git для тестов можно найти: https://gitlab.com/RalphEng/experiment-hibernate6-h2-datetime


Предыстория: вариант использования — Spring Tests. Запускаю Spring и память H2 для теста. И у меня есть много тестов, которые содержат такие тесты, как:

MyEntity myEntity = new MyEntity ();
myEntity.timestamp = LocalDateTime.now();
myEntity.xzy = ....

entityManager.persist(myEntity);
entityManager.flush();
entityManager.clear();

MyEntity reloaded = entityManager.find(MyEntity .class, myEntity.getId());
assertThat(reloaded.timestamp).isEqualsTo(myEntity.timestamp)
//otherFieldsTo

Честно говоря, тесты в большинстве случаев не такие простые, и проверка того, что временная метка точно такая же, на самом деле не предназначена и не нужна. Но я не могу это исправить. Так что повышение точности — это всего лишь способ проведения тестов.

И поскольку это только «проблема» в тестах, я не могу добавить @Column(columnDefinition = "TIMESTAMP(9)"), потому что это также изменит поведение производства.

Возможно, самый простой способ — сохранить временную метку как длинную (наносекунды), до GMT: Friday, 11 April 2262 23:47:16.854

Andrzej Więcławski 07.07.2024 15:34

@AndrzejWięcławski, ты не можешь хранить это в long - оно не поместится. Вот почему Instant приходится рассматривать нано отдельно

g00se 07.07.2024 15:43

Вы уверены, что хотите LocalDateTime? Если вы отслеживаете определенные точки на временной шкале, это неправильный класс.

Basil Bourque 07.07.2024 15:48

Вы понимаете, что аппаратные часы обычных компьютерных часов не могут отслеживать дату и время с точностью до наносекунд? Они делают это за микросекунды.

Basil Bourque 07.07.2024 15:49
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
4
64
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Решение Hibernate6 состоит в том, чтобы использовать собственный диалект и переопределить метод getDefaultTimestampPrecision для возврата 9:

public class CustomH2Dialect extends H2Dialect {    

    @Override
    public int getDefaultTimestampPrecision() {
        return 9;
    }
}

Извините, но где? github.com/hibernate/hibernate-orm/blob/main/hibernate-core/‌​src/… <- Я не могу найти ни одного getDefaultTimestampPrecision метода :/

Andrzej Więcławski 07.07.2024 15:08

@vampYr09 - спасибо, но: //миллисекунды или микросекунды — это максимум //для большинства диалектов, поддерживающих явную //точность, за исключением Oracle, //который принимает до 9 цифр, и DB2, //который принимает до 12 цифр!

Andrzej Więcławski 07.07.2024 17:26

Другие вопросы по теме