10. Как мапятся даты (до Java 8 и после)?

10. Как мапятся даты (до Java 8 и после)?

UNKNOWN

При работе с датами рекомендуется установить определенный часовой пояс для драйвера  JDBC.  Таким  образом,  наше  приложение  будет  независимым  от  текущего часового пояса системы.

Другой  способ  -  настроить  свойство  hibernate.jdbc.time_zone  в  файле  свойств Hibernate,  который  используется  для  создания  фабрики  сессий.  Таким  образом,  мы можем указать часовой пояс один раз для всего приложения. 

java.sql

Hibernate  позволяет  отображать  различные  классы  даты/времени  из  Java  в таблицах баз данных. Стандарт SQL определяет три типа даты/времени:

  1. DATE - Представляет календарную дату путем хранения лет, месяцев и дней. Эквивалентом JDBC является java.sql.Date.
  2. TIME - Представляет время дня и хранит часы, минуты и секунды. Эквивалентом JDBC является java.sql.Time.
  3. TIMESTAMP - Хранит как DATE, так и TIME плюс наносекунды. Эквивалентом JDBC является java.sql.Timestamp.

Поскольку  эти  типы  соответствуют  SQL,  их  сопоставление  относительно простое. Мы можем использовать аннотацию @Basic или @Column:

@Entity

public class TemporalValues {

    @Basic

    private java.sql.Date sqlDate;

    @Basic

    private java.sql.Time sqlTime;

    @Basic

    private java.sql.Timestamp sqlTimestamp;

}

Затем мы могли бы установить соответствующие значения следующим образом:

temporalValues.setSqlDate(java.sql.Date.valueOf(\"2017-11-15\"));

temporalValues.setSqlTime(java.sql.Time.valueOf(\"15:30:14\"));

temporalValues.setSqlTimestamp(java.sql.Timestamp.valueOf(\"2017-11-15 15:30:14.332\"));

Обратите внимание, что использование типов java.sql для полей сущностей не всегда может быть хорошим выбором. Эти классы специфичны для JDBC и содержат множество устаревших функций.

Чтобы избежать зависимостей от пакета java.sql, начали использовать классы даты/времени из пакета java.util вместо классов java.sql.Timestamp и java.sql.Time.

java.util

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

Поскольку классы в данном API изменяемые (не immutable), использовать их в многопоточной среде нужно с осторожностью. В частности java.util.Date можно признать «эффективно» потоко-безопасным, если вы не вызываете у него устаревшие методы.

java.util.Date

Тип  java.util.Date  содержит  информацию  о  дате  и  времени  с  точностью  до миллисекунд. Но так как классы из этого пакета не имели прямого соответствия типам данных  SQL,  приходилось  использовать  над  полями  java.util.Date  аннотацию @Temporal, чтобы дать понять SQL, с каким конкретно типом данных она работает. Для этого  у  аннотации  @Temporal  нужно  было  указать  параметр  TemporalType,  который принимал одно из трёх значений: DATE, TIME или TIMESTAMP, что позволяло указать базе данных с какими конкретными типами данных она работает.

@Basic

@Temporal(TemporalType.DATE)

private java.util.Date utilDate;

@Basic

@Temporal(TemporalType.TIME)

private java.util.Date utilTime;

@Basic

@Temporal(TemporalType.TIMESTAMP)

private java.util.Date utilTimestamp;

Тип  java.util.Date  имеет  точность  до  миллисекунд,  и  недостаточно  точен  для обработки  SQL-значения  Timestamp,  который  имеет  точность  вплоть  до наносекунд.

Поэтому, когда мы извлекаем сущность из базы данных, неудивительно, что в этом поле мы  находим  экземпляр  java.sql.Timestamp,  даже  если  изначально  мы  сохранили java.util.Date. Но это не страшно, так как Timestamp наследуется от Date. 

java.util.Calendar

Как  и  в  случае  java.util.Date,  тип  java.util.Calendar  может  быть  сопоставлен  с различными  типами  SQL,  поэтому  мы  должны  указать  их  с  помощью  @Temporal.

Разница лишь в том, что Hibernate не поддерживает отображение (маппинг) Calendar на TIME:

@Basic

@Temporal(TemporalType.DATE)

private java.util.Calendar calendarDate;

@Basic

@Temporal(TemporalType.TIMESTAMP)

private java.util.Calendar calendarTimestamp;

java.time

Начиная с Java 8, доступен новый API даты и времени для работы с временными значениями. Этот API-интерфейс устраняет многие проблемы классов java.util.Date и java.util.Calendar. Все классы в новом API неизменяемые (immutable) и, как следствие, потоко-безопасные.  Точность  представления  времени  составляет  одну  наносекунду, что  в  миллион  раз  точнее  чем  в  пакете  java.util.  Типы  данных  из  пакета  java.time напрямую  отображаются  (маппятся)  на  соответствующие  типы  SQL.  Поэтому  нет необходимости явно указывать аннотацию @Temporal:

  1. LocalDate соответствует DATE.
  2. LocalTime и OffsetTime соответствуют TIME.
  3. Instant, LocalDateTime,  OffsetDateTime  и  ZonedDateTime  соответствуют TIMESTAMP.

Это означает, что мы можем пометить эти поля только аннотацией @Basic (или @Column), например:

@Basic

private java.time.LocalDate localDate;

@Basic

private java.time.LocalTime localTime;

@Basic

private java.time.OffsetTime offsetTime;

@Basic

private java.time.Instant instant;

@Basic

private java.time.LocalDateTime localDateTime;

@Basic

private java.time.OffsetDateTime offsetDateTime;

@Basic

private java.time.ZonedDateTime zonedDateTime;

Каждый временной класс в пакете java.time имеет статический метод parse() для анализа предоставленного значения типа String с использова нием соответствующего формата. Итак, вот как мы можем установить значения полей сущности:

temporalValues.setLocalDate(LocalDate.parse(\"2017-11-15\"));

temporalValues.setLocalTime(LocalTime.parse(\"15:30:18\"));

temporalValues.setOffsetTime(OffsetTime.parse(\"08:22:12+01:00\"));

temporalValues.setInstant(Instant.parse(\"2017-11-15T08:22:12Z\"));

temporalValues.setLocalDateTime(

  LocalDateTime.parse(\"2017-11-15T08:22:12\"));

temporalValues.setOffsetDateTime(

  OffsetDateTime.parse(\"2017-11-15T08:22:12+01:00\"));

temporalValues.setZonedDateTime(

  ZonedDateTime.parse(\"2017-11-15T08:22:12+01:00[Europe/Paris]\"));


Предыдущий вопрос: 9. Как мапятся Enum`ы?

Следующий вопрос: 11. Как сохранять в базе данных коллекции базовых типов?

Все вопросы по теме: список

Все темы: список

Вопросы/замечания/предложения/нашли ошибку: напишите мне

Report Page