【发布时间】: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