Как настроить jadira PersistentLocalDateTime с помощью java.time.LocalDateTime?

Я пытаюсь упорствовать java.time.LocalDateTime используя Hibernate и JPA. Я использовал Jadira Framework ("org.jadira.usertype:usertype.core:3.2.0.GA" & "org.jadira.usertype:usertype.extended:3.2.0.GA"). я создал package-info.java файл и создан @TypeDefs({@TypeDef(defaultForType = java.time.LocalDateTime.class, typeClass = org.jadira.usertype.dateandtime.threeten.PersistentLocalDateTime.class)}) там. Я проверил решение и java.time.LocalDateTime поля хранятся / извлекаются в моей базе данных MySQL в DATETIME столбцы (почти) правильно.

Единственная проблема заключается в том, что значения в базе данных составляют +2 часа к правильному значению времени из полей в Java. Я нахожусь в CEST (UTC+2), поэтому я понял, что это некоторая проблема с часовыми поясами. Я отладил код PersistentLocalDateTime и это то, что я нашел.

  1. PersistentLocalDateTime использует org.jadira.usertype.dateandtime.threeten.columnmapper.AbstractTimestampThreeTenColumnMapper
  2. AbstractTimestampThreeTenColumnMapper имеет поле ZoneOffset databaseZone по умолчанию установлено ZoneOffset.of("Z") (УНИВЕРСАЛЬНОЕ ГЛОБАЛЬНОЕ ВРЕМЯ).
  3. Поскольку он думает, что моя база данных находится в часовом поясе UTC (а приложение в UTC + 2), это добавляет два часа к моему времени при преобразовании в базу данных (и вычитает два часа из моего времени при преобразовании из базы данных). Поэтому в приложении я вижу правильную дату и время, а в базе данных - нет.

Я обнаружил, что может добавить параметры в @TypeDef поэтому я указал их как ниже:

@TypeDef(defaultForType = LocalDateTime.class, typeClass = PersistentLocalDateTime.class,
    parameters = {
        @Parameter(name = "databaseZone", value = "+02:00")
    }),

но у меня есть исключение:

java.lang.IllegalStateException: Could not map Zone +02:00 to Calendar
at org.jadira.usertype.dateandtime.threeten.columnmapper.AbstractTimestampThreeTenColumnMapper.getHibernateType(AbstractTimestampThreeTenColumnMapper.java:59)

Я отладил немного больше. AbstractTimestampThreeTenColumnMapper имеет два метода:

public final DstSafeTimestampType getHibernateType() {

    if (databaseZone == null) {
        return DstSafeTimestampType.INSTANCE;
    }

    Calendar cal = resolveCalendar(databaseZone);
    if (cal == null) {
        throw new IllegalStateException("Could not map Zone " + databaseZone + " to Calendar");
    }

    return new DstSafeTimestampType(cal);
}

private Calendar resolveCalendar(ZoneOffset databaseZone) {

    String id = databaseZone.getId();
    if (Arrays.binarySearch(TimeZone.getAvailableIDs(), id) != -1) {
        return Calendar.getInstance(TimeZone.getTimeZone(id));
    } else {
        return null;
    }
}

getHibernateType Метод выдает исключение, потому что resolveCalendar метод возвращает null, Почему это возвращается null? Потому что идентификаторы часовых поясов от java.time.ZoneOffset а также java.util.TimeZone не совпадает. Насколько я вижу единственное возможное значение, которое соответствует Z, Любые другие значения вызывают исключения.

Есть ли способ настроить это правильно? Или это ошибка в Jadira Framework?

1 ответ

Это похоже на серьезную ошибку. Проблема в том, что параметр jadira.usertype.databaseZone анализируется в ZoneOffset вместо ZoneId. Таким образом, метод resolCalendar сравнивает 2 разных типа зоны и смещения. Что забавно, параметр называется databaseZone, но он не содержит зоны. Содержит только смещение.

https://github.com/JadiraOrg/jadira/issues/42

https://github.com/JadiraOrg/jadira/issues/43

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