根据当前日期+时间查询 JPA 实体以获取实例的最佳方法是啥?

Posted

技术标签:

【中文标题】根据当前日期+时间查询 JPA 实体以获取实例的最佳方法是啥?【英文标题】:What is the best way to query a JPA entity for instances based on the current date+time?根据当前日期+时间查询 JPA 实体以获取实例的最佳方法是什么? 【发布时间】:2014-03-18 09:57:23 【问题描述】:

我有一个实体类型,它有两个日期,startDate 和 endDate:

import org.joda.time.DateTime;

@Entity
public class Thing 
    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    private DateTime startDate;

    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    private DateTime endtDate;

我有一个用于此实体类型的 Spring Data-JPA 存储库(扩展 CrudRepository),在其中我需要一种方法来查询所有“活动”Things,其中“活动”定义为

开始日期

我尝试了这样的 JPQL 查询,但在我们的一些测试中它没有产生预期的结果:

@Query("select t from Thing t where t.startDate <= CURRENT_TIMESTAMP and t.endDate >= CURRENT_TIMESTAMP")
public Iterable<Thing> findAllActive();

我还尝试了一个方法名称约定查询,它确实产生了我期望的结果,但它很尴尬:

public Iterable<Thing> findByStartDateBeforeAndEndDateAfter(DateTime minStartDate, DateTime maxEndDate);

我可以把它包装在我的@Service

public Iterable<Thing> getActiveThings() 
    DateTime now = DateTime.now();
    return repository.findByStartDateBeforeAndEndDateAfter(now, now);

所以服务接口是干净的,但是 repo 接口是丑陋和尴尬的(在我看来)。

有没有更好的方法来使用 JPA 构造这个 Repository 查询方法,更好的基于方法名称的查询或显式 JPQL 查询?我宁愿不必在代码中手动构造 Query 对象(现在我什至没有 Repository 的具体类,只有一个接口),但如果这是最好的方式,我会考虑。

【问题讨论】:

CURRENT_TIMESTAMP的值是多少? CURRENT_TIMESTAMP 是 JPQL 中的内置函数,用于返回数据库中的当前日期+时间。见***.com/a/1659088/639520 我已经编写了涉及日期比较的 JPQL 查询,该查询工作正常,但我使用的默认 Date 类型与您指定的类型不同。尝试使用java.util.Date 来查看@Type 是否导致问题。 首先,检查 JPQL 转换为什么,并验证存储是否可以使用您选择的日期类型处理比较。 @TheKojuEffect,我们不会更改实体以使用 java.util.Date,Joda Time 库功能更多,我们已经在应用程序中基于它的逻辑。我知道它支持比较,因为方法名称版本有效(它只是丑陋)。 【参考方案1】:

您可以编写一个解决方法,如下所示:

@Query("SELECT t FROM Thing t WHERE t.startDate <= :maxStartDate AND :minEndDate <= t.endDate")
public Iterable<Thing> findAllActive();

并创建 DateTime maxStartDateDateTime minEndDate,例如2015-01-01 00:00:002015-01-01 23:59:59

DateTime maxStartDate= new DateTime().withTime(23, 59, 59, 0);
DateTime minEndDate = new DateTime().withTimeAtStartOfDay();

【讨论】:

【参考方案2】:

您可以简单地拥有以下内容:

@Query("select t from Thing t where t.startDate <= :time and t.endDate >= :time")
public Iterable<Thing> findActiveThings(@Param("time") DateTime time);

它的优点是仅使用 1 个参数,但也允许您稍后进行查询,例如:“给我 2011 年 1 月 24 日活动事物的列表”

【讨论】:

以上是关于根据当前日期+时间查询 JPA 实体以获取实例的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

JPA 一个实体中的两个惰性集合 - 如何运行 JPA 查询以获取实体和只有一个集合

Spring Data JPA Repository:如何有条件地获取子实体

Spring Jpa实体实例化失败:org.springframework.orm.jpa.JpaSystemException: No default constructor for entity

通过 JPA 标准查询从 SQL 视图获取列表时出错

JPA 为每个项目选择最新实例

如何通过 JPA 查询按子类实体值获取父实体?