首页 > 解决方案 > 在 HQL 中查找日期之间的实体

问题描述

我正在使用 HQL 和javax.persistence. 在我的 MySQL 数据库中,我有一个日期时间(例如2018-01-22 18:00:00)。从客户端,我被传递了一个没有时间的日期(例如2018-01-20)。我想找到日期时间在 astartDate和a 之间的所有实体endDate

public List<BillingRunEntity> getBillingRuns(List<String> accountIds, LocalDate startDate, LocalDate endDate) {
    String query = "SELECT DISTINCT bre " +
               "FROM BillingRunEntity bre " +
               "WHERE bre.accountId in :accountIds " +
               "AND bre.billingDateTime BETWEEN :startDate AND :endDate";

    return entityManager
        .createQuery(query, BillingRunEntity.class)
        .setParameter("accountIds", accountIds)
        .setParameter("startDate", startDate)
        .setParameter("endDate", endDate)
        .getResultList();
}

而我BillingRunEntity.javabillingDateTime领域:

@Column(name = "billing_date_time")
private ZonedDateTime billingDateTime;

1)尝试运行此查询会导致以下错误。考虑到我不在乎时间,我该如何解决这个问题?

java.lang.IllegalArgumentException: Parameter value [2018-07-03] did not match expected type [java.time.ZonedDateTime (n/a)]
    at org.hibernate.jpa.spi.BaseQueryImpl.validateBinding(BaseQueryImpl.java:874)
    at org.hibernate.jpa.internal.QueryImpl.access$000(QueryImpl.java:80)
    at org.hibernate.jpa.internal.QueryImpl$ParameterRegistrationImpl.bindValue(QueryImpl.java:248)
    at org.hibernate.jpa.spi.BaseQueryImpl.setParameter(BaseQueryImpl.java:620)
    at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:180)
    at org.hibernate.jpa.spi.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:49)

2)这个查询会按我期望的方式工作吗?我不关心这里的时间 - 如果数据库有2018-01-22 18:00:00,并且我通过了startDate一个(或什至)2018-01-22的结束日期,我希望提取该记录。2018-01-232018-01-22

标签: javahibernatejpahql

解决方案


假设您ZonedDateTime在数据库中始终存储在 UTC 中,您可以简单地转换为LocalDate

ZoneId utc = ZoneId.of("UTC");
ZonedDateTime startTime = startDate.atStartOfDay(utc);
ZonedDateTime endTime = endDate.atStartOfDay(utc).plusDays(1).minusNanos(1);

[...]

    .setParameter("startDate", startTime)
    .setParameter("endDate", endTime)

minusNanos(1)可能是矫枉过正,但BETWEEN运营商在两端都具有包容性。

如果您没有对数据库中的所有值使用相同的时区,您可能必须深入研究billing_date_time表使用的列类型以了解它如何处理时区信息。


推荐阅读