Hibernate 6.1.x中extract epoch函数失效问题求助
问题解决:Hibernate 6.1.x中extract(epoch from ...)解析异常
问题原因
Hibernate 6对HQL的语法校验更严格,epoch并非JPA标准extract函数支持的字段,属于Hibernate 5时期的非标准扩展,在Hibernate 6中默认不再支持该扩展;而year是JPA标准明确支持的字段,因此可以正常执行。
解决方案
方案1:使用原生SQL查询
直接使用数据库原生SQL,绕过HQL的语法校验,因为数据库本身支持extract(epoch from ...):
@Query(value = "SELECT CAST(EXTRACT(EPOCH FROM tx.date_created) AS BIGINT) " + "FROM transaction_history tx " + "WHERE tx.id = :id", nativeQuery = true) List<Long> findTimeStats(@Param("id") final String id);
注意:需将实体类名/字段名替换为数据库实际的表名/列名。
方案2:注册自定义HQL函数
通过自定义函数让Hibernate 6支持extract(epoch):
- 创建自定义函数类(以PostgreSQL为例):
public class EpochExtractFunction extends StandardSQLFunction { public EpochExtractFunction() { super("extract", StandardBasicTypes.LONG); } @Override public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor factory) throws QueryException { if (arguments.size() != 2) { throw new QueryException("extract(epoch from ...) requires exactly two arguments"); } return "extract(epoch from " + arguments.get(1) + ")"; } }
- 在Spring Boot中注册该函数:
@Configuration public class HibernateConfig { @Bean public HibernatePropertiesCustomizer hibernatePropertiesCustomizer() { return properties -> properties.put( "hibernate.query.functions.extract", EpochExtractFunction.class.getName() ); } }
注册完成后即可继续使用原HQL语句。
方案3:用JPA标准函数计算epoch
通过TIMESTAMPDIFF函数计算从1970-01-01到目标时间的秒数,兼容所有JPA实现:
@Query(value = "SELECT CAST(TIMESTAMPDIFF(SECOND, '1970-01-01 00:00:00', tx.dateCreated) AS LONG) " + "FROM TransactionHistory tx " + "WHERE tx.id = :id") List<Long> findTimeStats(@Param("id") final String id);
注意:不同数据库对TIMESTAMPDIFF的参数格式/顺序要求可能不同,需根据使用的数据库类型适配。
内容的提问来源于stack exchange,提问作者user2239251
相关产品推荐
相关产品推荐

