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 o.h.type.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上。
非常感谢。
答案 0 :(得分:1)
问题的答案就在于此。 Hibernate还不支持java.time类(它将在5.0版本中)。因此,它将LocalTime视为Serializable实例,并将序列化的LocalTime实例作为字节数组存储在varbinary列中。因此,>
运算符在这种类型的列上没有多大意义,并且不会按时间顺序比较LocalTime值。
您可以定义自己的自定义Hibernate类型,或使用jadira(为您定义此自定义类型),将LocalTime值存储在适当的列类型中。
答案 1 :(得分:1)
如果没有进一步的映射信息,Hibernate会将JDK 8日期视为BLOB,因此不再对这些字段应用任何比较操作。
对此的一个解决方案是使用Jadira User Types library来自定义这些类型映射到数据库的方式。
如果您只处理非时间分区类型(例如LocalDate
,LocalDateTime
),最简单的方法是使用Spring Data JPA 1.8附带的JPA 2.1转换器。只需确保Jsr310JpaConverters
是持久类的列表(通过扫描相应的包或在persistence.xml
中手动列出该类),这些JDK 8特定的日期/时间类型将映射到{{1透明地使任何持久性提供程序可以立即持久化它们。在blog post announcing new features in the Spring Data Fowler release train。