Spring Boot 3.1.11升级到3.2.5后Hibernate日期运算报错求助
问题原因及解决方案
根因
Spring Boot 3.2.5 配套的 Hibernate 6 对 JPQL 的类型检查变得更严格。之前版本中允许直接对日期类型做数值加减(比如current_date-60),但现在要求必须使用**时间量类型(TemporalAmount)**或标准日期函数来进行日期运算,否则就会抛出SemanticException错误。
等效实现方案
针对你的 Oracle 数据库场景,推荐使用 Hibernate 6 支持的DATEADD函数来替代直接的数值加减,该函数会自动转换为 Oracle 兼容的 SQL 语法。
示例1修复
原代码:
@Repository interface APCheckRepository extends JpaRepository<APCheck, Long> { @Query("select abc from TestTable abc" + " WHERE abc.checkDate >= ORACLE_TRUNC(current_date-60)") List<TestTable> findSomething(); }
修复后:
@Repository interface APCheckRepository extends JpaRepository<APCheck, Long> { @Query("select abc from TestTable abc" + " WHERE abc.checkDate >= ORACLE_TRUNC(DATEADD('day', -60, CURRENT_DATE))") List<TestTable> findSomething(); }
DATEADD('day', -60, CURRENT_DATE)等价于原逻辑中“当前日期减60天”的操作,Hibernate 会将其翻译为 Oracle 原生的CURRENT_DATE - 60语法。
示例2修复
原代码中的时间加减逻辑(如0.5/24代表30分钟)可以通过DATEADD指定更清晰的时间单位来实现:
原代码:
@Query("select d from TestTable2 d where " + " d.dateOfService-(0.5/24) <= :dosTo " // dateOfService within 30 mins of dosTo + " and d.dateOfService-(23/24) <= :dos " // dateOfService within 23 hours of dos + " and d.dateOfServiceTo-(24.5/24) <= :dos " // dateOfServiceTo within 24 1/2 hours of dos + "order by" + " d.quantity") List<TestTable2> findSomething2( @Param("dos") Date dos, @Param("dosTo") Date dosTo);
修复后:
@Query("select d from TestTable2 d where " + " DATEADD('minute', -30, d.dateOfService) <= :dosTo " // dateOfService within 30 mins of dosTo + " and DATEADD('hour', -23, d.dateOfService) <= :dos " // dateOfService within 23 hours of dos + " and DATEADD('hour', -24.5, d.dateOfServiceTo) <= :dos " // dateOfServiceTo within 24 1/2 hours of dos + "order by" + " d.quantity") List<TestTable2> findSomething2( @Param("dos") Date dos, @Param("dosTo") Date dosTo);
如果你更倾向于保留“天数分数”的写法,也可以用:
DATEADD('day', -(0.5/24), d.dateOfService) <= :dosTo
额外说明
- 你的自定义方言无需额外修改,Hibernate 6 的 Oracle 方言已内置对
DATEADD函数的支持,会自动转换为 Oracle 可识别的日期运算语法。 - 如果需要使用数据库服务器时区的时间(而非 JVM 时区),可以将
CURRENT_DATE替换为FUNCTION('SYSDATE'),比如:ORACLE_TRUNC(DATEADD('day', -60, FUNCTION('SYSDATE')))
内容的提问来源于stack exchange,提问作者coloradoman
相关产品推荐
相关产品推荐

