QueryDSL截断日期

时间:2018-08-09 08:39:02

标签: spring querydsl

我需要在两次查询之间使用querydsl进行日期比较,而没有时间戳。

QueryDsl:

Date startDate=
Date endDate=
QEmp qEmp=

BooleanExpression empExp = qEmp.id.dob.between(startDate, endDate);

表格:

select dob from employee where eid=2;
10-MAR-07 12.00.00.000000000 AM

dob之间的SQL查询:

select * from employee where dob between trunc(start date) and trunc(end dat)

这将查找开始日期和结束日期之间的记录,而没有时间戳。我需要在QueryDSl中执行同样的操作。数据库是Oracle。

1 个答案:

答案 0 :(得分:0)

不幸的是,DATE_TRUNC不是JPQL中定义的函数,因此,没有JPA实现(例如Hibernate)支持该功能。

但是,可以在各种JPA实现中将

DATE_TRUNC注册为自定义功能,然后可以使用QueryDSL Templates的自定义集来包括对这些功能的处理。

例如,对于Hibernate:

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中的日期/时间操作具有开箱即用的支持。