很遗憾,DATE_TRUNC 不是JPQL 中定义的函数,因此,没有任何 JPA 实现(例如 Hibernate)支持此函数。
DATE_TRUNC 但是可以在各种 JPA 实现中注册为自定义函数,然后您可以使用一组自定义 QueryDSL Templates 来包含对这些函数的处理。
例如,对于休眠:
public class DateTruncMetadataBuilderInitializer
implements MetadataBuilderInitializer {
@Override
public void contribute(MetadataBuilder metadataBuilder,
StandardServiceRegistry serviceRegistry) {
metadataBuilder.applySqlFunction("DATE_TRUNC",
new SQLFunctionTemplate(DateType.INSTANCE,
"DATE_TRUNC(?1, ?2)"));
}
}
然后您需要在名为 META-INF/services/org.hibernate.boot.spi.MetadataBuilderInitializer 的 JAR 资源文件中注册此类。
进行此更改后,您可以在 JPQL/HQL 查询中使用 DATE_TRUNC,如下所示:
SELECT a FROM Entity a
WHERE a.dateField BETWEEN DATE_TRUNC('day', :start) AND DATE_TRUNC('day', :end)
现在你必须让这个函数对 QueryDSL 可用。你可以通过声明一个自定义模板来做到这一点:
public class MyTemplates extends JPQLTemplates {
public MyTemplates() {
add(DateTimeOps.TRUNC_DAY, "DATE_TRUNC('day', {0})");
}
}
然后按如下方式使用:
new JPAQuery(entityManager, new MyTemplates()).from(entity)
.select(Expressions.dateOperation(DateTimeOps.TRUNC_HOUR, dateExpression))
但是,由于中间有 Spring 集成,Templates 绑定到我认为的查询有点困难。
或者,您可以查看blaze-persistence-querydsl 扩展,它对 JPQL 中的日期/时间操作具有开箱即用的支持。