Советы JPA: как отобразить атрибут Duration

  1. Вопрос:
  2. Не хочешь читать? Вы можете посмотреть это здесь!
  3. Решение:
  4. Hibernate делает это легко
  5. JPA требует немного работы
  6. Получите этот совет Hibernate в формате PDF для печати!
  7. Учить больше:

Hibernate Советы   это серия постов, в которых я описываю быстрое и простое решение общих вопросов Hibernate

Hibernate Советы это серия постов, в которых я описываю быстрое и простое решение общих вопросов Hibernate. Если у вас есть вопрос по будущему Hibernate Tip, оставьте комментарий ниже.

Вопрос:

В JPA 2.2 не добавлена ​​поддержка java.time.Duration . Как я могу сопоставить атрибут этого типа с JPA?

Не хочешь читать? Вы можете посмотреть это здесь!


Посмотри это видео на YouTube

Решение:

К сожалению, JPA 2.2 поддерживает только некоторые классы API даты и времени, и java.time.Duration не является одним из них. Если вы ограничены простым JPA, вам необходимо реализовать пользовательское сопоставление для атрибутов типа Duration . Как вы увидите, это не так сложно, как может показаться.

Hibernate делает это легко

Но прежде чем мы углубимся в детали, я хочу показать вам более удобный подход. Начиная с версии 5, Hibernate поддерживает java.time.Duration в качестве базового типа. , Таким образом, если вам разрешено использовать проприетарные функции Hibernate, вы можете использовать атрибуты сущностей типа Duration без каких-либо дополнительных аннотаций сопоставления.

@Entity открытый класс OnlineCourse {@Id @GeneratedValue private Длинный идентификатор; частное название строки; частная продолжительность видеодлительность; ...}

JPA требует немного работы

Если вы не используете Hibernate или если некоторые внутренние правила запрещают вам использовать проприетарные функции, вы можете реализовать собственное отображение с помощью простого AttributeConverter , В этом конвертере необходимо сопоставить неподдерживаемый объект Duration с объектом поддерживаемого типа.

Например, вы можете преобразовать объект Duration в long, который представляет количество наносекунд длительности. Просто знайте, что это ограничивает вашу продолжительность чуть более 292 лет. Этого должно быть достаточно для большинства приложений. Если вам нужно хранить более длительную продолжительность, вам нужно будет уменьшить точность, например, сохранить количество миллисекунд.

Реализация такого преобразователя относительно проста. Вам просто нужно реализовать AttributeConverter Интерфейс <Duration, Long> и аннотируйте класс @Converter аннотаций. Вам следует установить для атрибута autoApply аннотации значение true. Это говорит провайдеру персистентности использовать конвертер для всех атрибутов сущности типа java.time.Duration .

Здесь вы можете увидеть пример такого AttributeConverter . В методе convertToDatabaseColumn я вызываю метод toNanos объекта Duration, чтобы преобразовать его в long . И метод convertToEntityAttribute использует метод of с ChronoUnits.NANOS для реализации обратного преобразования.

@Converter (autoApply = true) открытый класс DurationConverter реализует AttributeConverter <Duration, Long> {Logger log = Logger.getLogger (DurationConverter.class.getSimpleName ()); @Override public Long convertToDatabaseColumn (атрибут Duration) {log.info ("Преобразовать в длинный"); return attribute.toNanos (); } @Override public Duration convertToEntityAttribute (Long duration) {log.info ("Преобразовать в длительность"); вернуть Duration.of (duration, ChronoUnit.NANOS); }}

Это все, что вам нужно сделать. Теперь вы можете использовать объект OnlineCourse, который я показал вам в начале этого поста. Ваш поставщик сохраняемости автоматически применяет DurationConverter, так что вам не нужно адаптировать отображение сущностей.

// Транзакция 1: сохранить новую сущность OnlineCourse EntityManager em = emf.createEntityManager (); em.getTransaction () начинается (). OnlineCourse c = новый OnlineCourse (); c.setTitle («Онлайн-тренировка по настройке производительности Hibernate»); c.setVideoDuration (Duration.parse ( "PT5H55M")); em.persist (с); em.getTransaction () фиксации (). em.close (); // Транзакция 2: чтение сущности OnlineCourse em = emf.createEntityManager (); em.getTransaction () начинается (). em.find (OnlineCourse.class, c.getId ()); log.info ("+ c.getTitle () +" содержит "+ c.getVideoDuration (). toMinutes () / 60+" часов и "+ c.getVideoDuration (). toMinutes ()% 60+" минут видео"); em.getTransaction () фиксации (). em.close ();

Как вы можете видеть в выходных данных журнала, DurationConverter вызывается дважды для сопоставления атрибута videoDuration :

  1. Когда сущность сохраняется, вызывается метод convertToDatabaseColumn для сопоставления Duration с длинным объектом
  2. Когда объект считывается из базы данных, вызывается метод convertToEntityAttribute для сопоставления объекта Long с объектом Duration.

17: 47: 15,197 DEBUG [org.hibernate.SQL] - выберите nextval ('hibernate_sequence') 17: 47: 15,241 DEBUG [org.hibernate.SQL] - вставьте в OnlineCourse (название, версия, videoDuration, id) значения (? ,?,?,?) 17: 47: 15,246 INFO [DurationConverter] - конвертировать в длинный 17: 47: 15,276 DEBUG [org.hibernate.SQL] - выберите onlinecour0_.id в качестве id1_0_0_, onlinecour0_.title в качестве title2_0_0_, onlinecour0_.version как version3_0_0_, onlinecour0_.videoDuration как videoDur4_0_0_ из онлайн-курса onlinecour0_, где onlinecour0_.id =? 17: 47: 15,290 INFO [DurationConverter] - преобразовать в продолжительность 17: 47: 15,294 INFO [org.blyts.on.java.model.TestAttributeConverter] - онлайн-тренинг по настройке производительности Hibernate содержит 5 часов и 55 минут видео

Получите этот совет Hibernate в формате PDF для печати!

Присоединяйтесь к бесплатной статье «Мысли о библиотеке Java», чтобы получить доступ к большому количеству контента, предназначенного только для членов, например, к печатному PDF для этого поста, множеству шпаргалок и 2 электронным книгам о Hibernate.

Учить больше:

AttributeConverter - это мощная и простая в использовании функция. Вы можете использовать его для:


Hibernate Советы


Как я могу сопоставить атрибут этого типа с JPA?
Не хочешь читать?
Id =?