【问题标题】:Java: JPQL date function to add a time period to another date [closed]Java:JPQL日期函数将时间段添加到另一个日期[关闭]
【发布时间】:2011-02-20 19:59:36
【问题描述】:
SELECT x FROM SomeClass
WHERE x.dateAtt BETWEEN CURRENT_DATE AND (CURRENT_DATE + 1 MONTH)

在上面的 JPQL 语句中,SomeClass 有一个 memebr dateAttr,它是一个java.util.Date,并有一个@Temporal(javax.persistence.TemporalType.DATE) 注释。

我需要一种方法来处理 (CURRENT_DATE + 1 MONTH) 位 - 在其当前状态下显然是错误的 - 但找不到带有 JPQL 日期函数的文档。

谁能给我指明一个记录 JPQL 日期函数(以及如何执行此特定查询)的文档的方向?

【问题讨论】:

  • 这是您想要的某种查询方式吗?或者这是否需要在它自己的实体 bean 上的触发器中?即:@PrePersist@PreUpdate?
  • @Shervin : 不,查询不需要在@PrePersist@PreUpdate 中执行。该查询是对 JPA 实体类 (SomeClass) 的命名查询。
  • @Shervin :另外,我知道我可以使用 Java 计算 Date 操作,然后使用 :parameter 将其传递到查询中,但是,我更愿意在JPQL 本身并避免不必要的代码。
  • 我明白了,因为这就是我建议的解决方法。我不确定这些功能是 JPA 标准的一部分。您使用的是哪个数据库?

标签: java date documentation jpql


【解决方案1】:

标准 JPQL 不支持此类日期操作。您将不得不使用本机查询或在 Java 端进行计算。

【讨论】:

  • 这仍然是真的吗?
【解决方案2】:

如果您的日期对象已经是 + 1 个月,您可以执行以下操作:

public List findEmployees(Date endDate) {
  return entityManager.createQuery(
    "SELECT e from Employee e WHERE e.startDate BETWEEN ?1 AND ?2")
    .setParameter(1,new Date(), TemporalType.DATE)
    .setParameter(2,endDate, TemporalType.DATE).getResultList();
}

但是,这要求日期事先有效。

更新

如果你总是想要下个月,你可以使用JodaTime,它有一个很棒且简单的api。 然后,您可以像这样修改您的查询:

//Get next month
DateTime dt = new DateTime();
entityManager.createQuery(
"SELECT e from Employee e WHERE e.startDate BETWEEN ?1 AND ?2")
.setParameter(1,new Date(), TemporalType.DATE)
.setParameter(2,dt.plusMonths(1).toDate(), TemporalType.DATE).getResultList();

【讨论】:

  • 你尝试过 JodaTime 部分吗? JPA 可以处理DateTime 吗?
  • @Pascal:好点。我忘记了 toDate() 方法。这将返回一个java.util.Date
  • 轻微改进:.setParameter(1, dt.toDate(), TemporalType.DATE)(少一个导入,与下一行保持一致)
  • 这并不能真正回答“JPQL 日期函数”的问题,因为 JPQL 本身就是一个查询规范,这里的答案是基于 Java/JPA 的解决方案。毫无疑问,获得解决方案的方法......再次,我认为“标准 JPQL 不 [不] 支持日期上的此类操作”下面的答案更正确。
【解决方案3】:

或者使用 commons-lang 代替 jodatime:

entityManager.createQuery(
    "SELECT e from Employee e WHERE e.startDate BETWEEN ?1 AND ?2"
)
.setParameter(1,new Date(), TemporalType.DATE)
.setParameter(2,DateUtils.addMonths(new Date(), 1), TemporalType.DATE)
.getResultList();

但我知道这不是你要问的,而且我很确定它不能单独在 JPQL 中完成,你要么必须传递参数,要么使用本机命名查询

【讨论】:

  • DateUtils?那是 std JDK 的一部分还是像 Joda time 这样的库?
  • 它在 apache commons / lang 中,这是一个被许多框架内部使用的开源库:commons.apache.org/lang
  • 最好使用 Joda-Time,因为它是 JSR-310 (jsr-310.dev.java.net) 的参考实现
  • 是的,但在我参与过的大多数项目中,commons / lang 已经在类路径中。而且我不认为上面看到的简单用法证明使用 joda 是合理的(如果不使用其他方式)
【解决方案4】:

亲爱的,

我正在使用spring数据,实体将createdDate保存为日期时间,并在存储库中像这样:

@Query(value="SELECT t FROM MyEntity t WHERE t.createdDate Between ?1 and ?2")
public List<MyEntity> findAllBetweenDates(Calendar from, Calendar to);

所以我不能使用:

setParameter(1,new Date(), TemporalType.DATE

在后端 bean 中,我使用以下内容:

    //to set zero of hours,minutes,seconds and milliseconds
    fromCalendar.set(java.util.Calendar.HOUR, 0);
    fromCalendar.set(java.util.Calendar.MINUTE, 0);
    fromCalendar.set(java.util.Calendar.SECOND, 0);
    fromCalendar.set(java.util.Calendar.MILLISECOND, 0);

    toCalendar.set(java.util.Calendar.HOUR, 0);
    toCalendar.set(java.util.Calendar.MINUTE, 0);
    toCalendar.set(java.util.Calendar.SECOND, 0);
    toCalendar.set(java.util.Calendar.MILLISECOND, 0);
    // add 1 days and decrease 1 millisecond
    toCalendar.add(java.util.Calendar.DAY_OF_MONTH, 1);
    toCalendar.add(java.util.Calendar.MILLISECOND, -1);

    allEntities = myEntityRepository.findAllBetweenDates(fromCalendar, toCalendar);
}

它工作正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-20
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    • 1970-01-01
    • 1970-01-01
    • 2015-09-21
    相关资源
    最近更新 更多