Spring Data JPA自定义Query按LocalDate排序触发类型转换异常
问题分析
自定义@Query方法在传入包含noticeDate(LocalDate类型)的Pageable排序时,Hibernate错误地对日期字段应用了lower()函数,导致类型不匹配异常。派生查询能正常运行是因为Spring Data JPA会为派生查询正确识别字段类型,不会对日期字段添加lower()处理,而自定义@Query可能受到全局配置或自动排序转换逻辑的影响。
解决方案
1. 使用JpaSort.unsafe指定原始排序字段
创建Pageable时,通过JpaSort.unsafe()直接指定JPQL中的字段路径,跳过自动的大小写转换处理:
// 示例:创建按noticeDate降序的分页对象 Pageable pageable = PageRequest.of(0, 10, JpaSort.unsafe(Sort.Direction.DESC, "n.noticeDate"));
这种方式会让排序逻辑直接使用你在@Query中定义的实体别名(n是Notice的别名)对应的字段,避免Spring Data自动添加lower()函数。
2. 检查并调整全局排序配置
检查项目中是否存在以下配置:
spring.data.jpa.query.sort-case-insensitive=true
该配置会让Spring Data JPA对所有排序字段默认应用lower()函数以实现大小写不敏感排序,但不适用于日期类型字段。如果开启了这个配置,要么直接关闭,要么针对日期字段使用第一种方案的JpaSort.unsafe()来绕过。
3. 在@Query中手动整合排序逻辑
通过SpEL表达式#{#pageable.sort}将Pageable的排序逻辑直接嵌入到JPQL中,让排序直接使用实体字段,避免自动转换:
@Query(""" select distinct n from Notice n join fetch n.noticeType nt join n.deposit d where d.id = :id order by #{#pageable.sort} """) Page<Notice> findByDepositId(Long id, Pageable pageable);
注意:添加distinct关键字可以避免fetch join导致的分页重复记录问题,同时排序参数中的字段名需要与JPQL中的实体字段名一致(比如noticeDate)。
内容的提问来源于stack exchange,提问作者robert trudel
相关产品推荐
相关产品推荐

