Как настроить 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
и это то, что я нашел.
PersistentLocalDateTime
используетorg.jadira.usertype.dateandtime.threeten.columnmapper.AbstractTimestampThreeTenColumnMapper
AbstractTimestampThreeTenColumnMapper
имеет полеZoneOffset databaseZone
по умолчанию установленоZoneOffset.of("Z")
(УНИВЕРСАЛЬНОЕ ГЛОБАЛЬНОЕ ВРЕМЯ).- Поскольку он думает, что моя база данных находится в часовом поясе 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, но он не содержит зоны. Содержит только смещение.