【问题标题】:How to get Date Difference in hour using HQL如何使用 HQL 获取小时的日期差异
【发布时间】:2014-03-01 18:02:44
【问题描述】:

我必须以小时为单位获取当前日期和存储在数据库中的日期之间的差异。在 PostgreSQL 中,我可以使用以下查询来做到这一点:

SELECT storage_time, extract(epoch from (localtimestamp - storage_time))/3600 as diff_hour FROM some_table;

这给了我小时日期之间的差异:

      storage_time       |     diff_hour      
-------------------------+-------------------
 2014-02-03 19:37:39.481 |  44.4788805811111
 2014-02-03 19:40:28.201 |  44.4320139144444
 2014-01-29 18:25:12.828 |  165.686284192222
 2014-02-03 19:25:56.861 |  44.6740528033333
 2014-02-05 15:53:38.178 | 0.212575858888889
 2014-01-30 15:53:38.61  |  144.212455858889

现在,我在将其移植到 Hibernate 查询语言时遇到了困难。我尝试了很多变体,但我无法从日期差异中获取 epoch。这肯定行不通:

"FROM SomeEntity " +
"WHERE someAttribute = :attr " +
"AND epoch(localtimestamp - deviceInfo.storageTime) / 3600 > :threshold_hour";

当我运行这个命令时,我得到以下异常:

org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2102)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1835)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:500)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:388)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:273)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:93)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:56)
    at org.hibernate.loader.Loader.getResultSet(Loader.java:2040)
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1837)
    at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1816)
    at org.hibernate.loader.Loader.doQuery(Loader.java:900)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:342)
    at org.hibernate.loader.Loader.doList(Loader.java:2526)
    at org.hibernate.loader.Loader.doList(Loader.java:2512)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2342)
    at org.hibernate.loader.Loader.list(Loader.java:2337)
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:495)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:357)
    at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:195)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1275)
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101)

我这样运行查询:

Query query = sessionFactory.getCurrentSession()
                    .getNamedQuery(GET_NON_EXPIRED_ENTITY)
                    .setString("attr", attr)
                    .setInteger("threshold_hour", thresholdHour);

List<SomeEntity> instances = query.list();

当我调用 list() 时,第二行出现异常。

但是,当我将epoch() 函数更改为day() 时,在休眠查询中,它运行时没有异常,但当然会出现意外结果。

有什么方法可以在 HQL 中获得与 PostgreSQL 查询相同的行为?

【问题讨论】:

  • 不久前我尝试过这样做,但我似乎记得并放弃了。据我记得 HQL 中没有 API 可以做这样的事情 - 你需要求助于原生 SQL ...
  • @BoristheSpider :( :( 真的很伤心。:(
  • 也许一些hibernate Guru会出现并建议一些聪明的HQL结构。总有希望!
  • 作为另一种表达搜索方式的线索,您正在做的是将 SQL 时间戳转换为“unix 时间戳”、“纪元秒”或“朱利安日期”变体,即自纪元以来的秒数。我知道 JPA 和 JPQL / Criteria 缺乏对 interval 类型的支持,所以 HQL 可能也支持,但它们可能提供一些基本的东西,比如将时间戳转换为秒。虽然我总是在将它用于许多“实际工作”时遇到 Hibernate 限制,所以也许不会......
  • @CraigRinger 那么,目前除了迁移到原生 SQL 之外没有其他解决方法吗?

标签: java hibernate postgresql date hql


【解决方案1】:
  1. HQL supports EXTRACT(... FROM ...) 函数和 EPOCH 关键字,虽然文档中没有提到。
  2. HQL 还支持无参数 LOCALTIMESTAMP 函数(用于 Postgres 和 MySQL 方言)。这个事实也没有在文档中,但我在来源中找到了它(link1link2

所以,所需的 HQL 查询是:

FROM SomeEntity p 
WHERE EXTRACT(EPOCH FROM (LOCALTIMESTAMP-p.storageTime))/3600 > :threshold

【讨论】:

  • 这个答案不正确。 mySQL 中没有 EPOCH 函数并且生成的 MySQL 查询被破坏并且不起作用
  • 这个问题显然是关于 postgresql,而不是关于 mysql
  • 标题清楚地谈到了 HQL,答案清楚地谈到了 HQL,所以人们希望这个解决方案也可以在 mySQL 中工作,但事实并非如此......所以我认为帮助人们抽出时间尝试理解为什么它在 mySQL 中对他们不起作用..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-18
  • 1970-01-01
  • 1970-01-01
  • 2013-05-18
  • 2021-11-03
  • 2020-12-20
  • 1970-01-01
相关资源
最近更新 更多