2015-08-05 4 views
4

Я пытаюсь сохранить 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 (почти) правильно.Как настроить jadira PersistentLocalDateTime с java.time.LocalDateTime?

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

  1. PersistentLocalDateTime использует org.jadira.usertype.dateandtime.threeten.columnmapper.AbstractTimestampThreeTenColumnMapper
  2. AbstractTimestampThreeTenColumnMapper имеет поле ZoneOffset databaseZone по умолчанию установлен в ZoneOffset.of("Z") (UTC).
  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. Таким образом, метод resolveCalendar сравнивает 2 разных типа Zone и Offset. Что смешно, параметр называется databaseZone, но он не содержит зоны. Он содержит только смещение.

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

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

+0

Такое поведение адресуется 5.0.0.GA, отображающая через ZoneId. Отказ от ответственности: Я поддерживаю Джадиру. –

Смежные вопросы