根据当前日期+时间查询 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
),在其中我需要一种方法来查询所有“活动”Thing
s,其中“活动”定义为
开始日期
我尝试了这样的 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 maxStartDate
和 DateTime minEndDate
,例如2015-01-01 00:00:00
和 2015-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