如何使用 Joda Time 查询 HQL (Hibernate) 中的日期?

Posted

技术标签:

【中文标题】如何使用 Joda Time 查询 HQL (Hibernate) 中的日期?【英文标题】:How to query a date in HQL (Hibernate) with Joda Time? 【发布时间】:2010-12-23 10:08:03 【问题描述】:

相信熟悉HQL的人(我自己也是新手)可以轻松回答这个问题。

在我的 Grails 应用程序中,我有以下域类。

class Book 
  org.joda.time.DateTime releaseDate //I use the PersistentDateTime for persisting via Hibernate (that use a DATETIME type for mysql DB)

在我的 HQL 查询中,我想检索发行日期在date1..date2 范围内的书籍

例如我试过:

DateTime date1, date2
... 
def queryStr = "select * from Book as b where b.releaseDate > $date1 and b.releaseDate < $date2" 
def res = Book.executeQuery(queryStr)

但我得到了例外...caused by: org.springframework.orm.hibernate3.HibernateQueryException: unexpected token: 错误标记指向日期格式(例如 2009-11-27T21:57:18.010+01:00Fri Nov 27 22:01:20 CET 2009

我也尝试将 date1 转换为 Date 类,但没有成功

那么正确的 HQL 代码是什么?我应该使用 patternForStyle 方法转换为特定格式(哪一种?)还是有另一种 -cleaner- 方法可以做到这一点?

谢谢,

法比恩。

【问题讨论】:

org.joda.time.DateTime 如何映射到您的 SQL?是直接到外地吗? java.util.Date 和 java.util.Calendar 可以直接映射到数据库字段。值得一提的是,由于 DateTime 是一个聚合对象,Grails 插件可能正在使用自定义映射类型(参见 Java Persistence with Hibernate 的第 5.3 节)。 如代码注释中所述,DateTime 使用的是来自 joda-time-hibernate 库的 PersistentDateTime 自定义映射类型 【参考方案1】:

我不是 Grails 专家,但在 java 中,您通常会创建 date1date2 查询参数并像这样绑定它们:

String hql = "select * from Book as b where b.releaseDate > :date1 and b.releaseDate < :date2";
session.createQuery(hql).setDate("date1", date1).setDate("date2", date2).list();

我相信你可以在 Grails 中做类似的事情。如果没有,请将日期格式设置为 yyyyMMddhhmmss(无空格)并将它们括在单引号中 - 这样 Hibernate 会将它们视为常量,MySQL 会将它们隐式转换为日期。

【讨论】:

非常感谢!!在您回复之后,我进入 grails 源代码并找到了执行 HQL 查询的代码: Account.executeQuery("select distinct a.number from Account a where a.branch = :branch", [branch:'London'] ) 所以我对我的场景做了同样的事情,它奏效了。谢谢。【参考方案2】:

我通过 ChssPly 指出,您应该将 date1date2 声明为查询参数(位置或命名),然后绑定它们。在这里,我们将使用命名参数。使用 Grails 传递命名查询参数的常用方法是通过 Map:

def queryStr = "from Book b where b.releaseDate > :date1 and b.releaseDate < :date2"
Book.executeQuery(queryStr, [date1: date1, date2: date2])

查看executeQuery() 文档以了解这两个选项的语法详细信息。

【讨论】:

您好 Pascal 谢谢您的帮助。我完全按照你写的做了。【参考方案3】:

您还可以使用 ISO8601 日期格式比较日期,例如:

select * from Book as b 
where b.releaseDate > '2009-11-27T21:57:18.010+01:00' 
and b.releaseDate < '2010-11-27T21:57:18.010+01:00'

我已经使用 MySql 作为后端对此进行了测试。请记住将日期包装为字符串。

【讨论】:

以上是关于如何使用 Joda Time 查询 HQL (Hibernate) 中的日期?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Joda Time 进行 DST 转换

如何使用 Joda Time 解析包含时区的日期

如何从 org.joda.time.DateTime 转换为 java.time.ZonedDateTime

如何在 Joda Time 中检测模糊的 DST 重叠?

Joda-Time 中两个日期之间的天数

如何在没有 Joda Time 的情况下在 Java 7 中正确处理夏令时?