Подтвердить что ты не робот

Копирование TIMESTAMP в DATETIME на MySQL с Hibernate

У меня эти два класса

class Source {
    // mapped to TIMESTAMP
    @Version
    @Column(columnDefinition="TIMESTAMP(3) DEFAULT '2016-01-01'")
    Instant myInstant;
}

class Destination {
    // mapped to DATETIME
    @Basic(optional=true)
    Instant myInstant;
}

При использовании Hibernate я назначаю

destination.myInstant = source.myInstant;

а затем сохраненное значение меньше на один час, чем оригинал - как в соответствии с командной строкой MySQL-клиента, так и на Java. Мой текущий часовой пояс - UTC + 1, поэтому причиной является, очевидно, изменение часового пояса.

Есть несколько мест, где это можно исправить, но я ищу наилучшую практику. Сервер должен работать по всему миру, поэтому он должен продолжать использовать UTC внутренне, не так ли?

Должен ли я просто изменить тип столбца на TIMESTAMP? Затем, почему Instant по умолчанию сопоставляется с DATETIME?


Согласно в этой статье, Instant отображается на TIMESTAMP, но в моем случае это не так. Почему?

4b9b3361

Ответ 1

Если вы хотите работать с часовыми поясами и Java 8, я бы рекомендовал использовать ZonedDateTime или OffsetTimeZone (последний предпочитается при работе с Hibernate). Для более старых версий используйте Calendar.

  • Когда вы делаете экземпляр, он должен идти по умолчанию с часовым поясом вашего компьютера.
  • Проверьте, является ли база данных временной отметкой с часовым поясом или без нее.
  • Установленный по умолчанию параметр также не имеет часовой пояс, и если он "с часовым поясом", он должен автоматически добавлять смещение базы данных.

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

@Column(name = "registration_time")
private OffsetDateTime registrationTime;
[...]
subscriber.setRegistrationTime(OffsetDateTime.now());

Ответ 2

В MySQL 5 и выше значения TIMESTAMP преобразуются из текущего часового пояса в UTC для хранения и преобразуются обратно из UTC в текущий часовой пояс для извлечения. Это происходит только для типа данных TIMESTAMP, но не для DATETIME. Именно по этой причине вы видите разницу при назначении TIMESTAMP для DATETIME. Итак, нужно иметь обе колонки одного типа. Hibernate по умолчанию отображает InstantType в базу данных типа TIMESTAMP. Хотя вы можете использовать его как для TIMESTAMP, так и для DATETIME в MYSQL, они обрабатываются по-разному.