Механизм вывода запроса хранилища Spring Data (версия 1.8) не работает должным образом с Java 8 LocalTime. Может ли кто-нибудь сказать мне, если я ошибаюсь или это ошибка?
Я храню время начала в 10:00
LocalTime startingTime = LocalTime.of(10,0); myEntity.setHorai(startingTime); myEntityRepository.save(myEntity);
Затем я прошу всех сущностей, время начала которых больше 08:00:
LocalTime zeroEight = LocalTime.of(8, 0); List<MyEntity> ents = myEntityRepository.findByStartingTimeAfter(zeroEight);
Я вижу, что Hibernate (я использую Hibernate версии 4.3.7.Final) выполняет это:
Hibernate: select <all fields> from MyEntity m_ where m_.startingTime>? TRACE 2015-03-27 12:08:51,283 ohtype.descriptor.sql.BasicBinder: binding parameter [1] as [VARBINARY] - [08:00]
Таким образом, List должен содержать 1 элемент, но имеет 0 элементов. Если вместо findByStartingTimeAfter
я использую findByStartingTimeBefore
он возвращает 1 элемент, но я не уверен, что это потому, что я не понимаю, как работать до и после. Я пробовал с findByStartingTimeGreaterThan
но терпит неудачу таким же образом.
Может быть, механизм вывода запроса не работает с Java 8 LocalTime?
Возможно, проблема в Hibernate, которая не сравнивает правильно данные VARBINARY (я вижу, что LocalTime хранится как BLOB, но он правильно хранится и извлекается как LocalTime)?
Я использую postgres 9.2, но я не думаю, что проблема связана с postgres.
Большое спасибо.
Ответ в этом вопросе. Hibernate еще не поддерживает классы java.time (это будет в версии 5.0). Поэтому он рассматривает LocalTime как экземпляр Serializable и просто хранит сериализованный экземпляр LocalTime в виде байтового массива в столбце varbinary. Таким образом, оператор >
не имеет особого смысла в этом типе столбца и не будет сравнивать значения LocalTime в хронологическом порядке.
Вы можете определить свой собственный тип Hibernate или использовать jadira (который определяет этот настраиваемый тип для вас), чтобы сохранить значение LocalTime в соответствующем типе столбца.
Без дополнительной информации о сопоставлении Hibernate будет рассматривать даты JDK 8 как BLOB и, следовательно, больше не может применять какие-либо операции сравнения к этим полям.
Одним из решений этого является использование библиотеки пользовательских типов Jadira для настройки способа сопоставления этих типов в базе данных.
Если вы имеете дело только с не-временными зонами (например, LocalDate
, LocalDateTime
), самым простым способом является использование конвертеров JPA 2.1, поставляемых с Spring Data JPA 1.8. Просто убедитесь, что Jsr310JpaConverters
- это список постоянных классов (либо путем сканирования соответствующего пакета, либо вручную перечисления этого класса в вашем persistence.xml
), и эти конкретные типы даты и времени JDK 8 сопоставляются с Date
прозрачно, чтобы любой постоянный провайдер сохранялся их сразу. Дополнительную информацию об этом можно найти в блоге, в котором сообщается о новых функциях в выпуске Spring Data Fowler.