java - 通过导致 PSQLException 的 Hibernate 和 PostgreSQL 执行查询的差异

标签 java sql hibernate postgresql jpa

我想在 Postgres 9.4 数据库系统上通过 JPA 2.0 和版本 4.2.21 中的 Hibernate 执行 native SQL 查询。

基本上根据我最新的post在 stackoverflow 上,我尝试将大量对象/记录放入“时间”桶中。

设置可以简化为以下设置,其中包含一个带有 id 字段和给定时间戳的表“MyObject”:

CREATE TABLE myobject
(
  id bigint NOT NULL,
  lastseen timestamp without time zone, 
)

我的一段代码,应该执行查询是这个:

Query q = getEntityManager().createNativeQuery(
             "select count(id),date_part('day', :startDate - c.lastseen)  AS " +
             "difference from myobject c " +
             "group by date_part('day', :startDate - c.lastseen) order by difference asc");

q.setParameter("startDate", startDate);

List<Object[]> rawResults = q.getResultList();

//process the reuslts

通过 pgAdmin3 使用示例日期执行此查询会返回预期的结果。

但是,如果我尝试通过 Hibernate 执行与 native 查询相同的查询,它会失败并出现以下异常:

Caused by: org.postgresql.util.PSQLException:
FEHLER: column „myobject.lastseen“ must appear in the group by clause or be used in an aggregate function
  Position: 40
  at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2270)
  at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1998)
  at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
  at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:570)
  at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:420)
  at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:305)
  at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:79)
  ... 94 more

此异常似乎有效且不言自明,但为什么我可以通过 PgAdmin3 执行相同的查询? Hibernate SQL 解析器是否比 pgAdmin3 更严格,或者它是否弥补了一些错误?

那么如何制定我的 SQL 查询以使其通过 Hibernate 可执行?

编辑:

出于某种原因,以下 SQL 语句(带有显式子选择)可以通过 PgAdmin3 和 Hibernate 工作:

select count(id), difference
from (select c.id,c.lastseen,date_part('day', :startDate - c.lastseen) AS difference
      from myobject c) AS temporalBucket
group by difference
order by difference asc

但这仍然没有回答给定代码片段中先前查询的问题。

最佳答案

这个查询应该也能工作,没有子查询:

SELECT count(id)  -- or even better: count(*) AS ct
     , date_part('day', :startDate - c.lastseen) AS difference
FROM   myobject c 
GROUP  BY <b>difference</b>
ORDER  BY difference;

我怀疑的原因:Hibernate 使用prepared statements :startDate 的两次出现作为两个 参数传递。这样,Postgres 就不能假定两个表达式(在 SELECT 列表和 GROUP BY 中)是相同的......

用等效的 SQL command PREPARE 进行演示,这有效:

PREPARE test1 AS
SELECT count(*) AS ct
     , date_part('day', $1 - c.lastseen) AS difference
FROM   myobject c 
GROUP  BY date_part('day', <b>$1</b> - c.lastseen)
ORDER  BY difference;

虽然这不是:

PREPARE test2 AS
SELECT count(*) AS ct
     , date_part('day', $1 - c.lastseen) AS difference
FROM   myobject c 
GROUP  BY date_part('day', <b>$2</b> - c.lastseen)
ORDER  BY difference;

.. 并引发与您显示的相同的异常。

您可以使用我建议的查询先验地避免该问题。

相关:

关于java - 通过导致 PSQLException 的 Hibernate 和 PostgreSQL 执行查询的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34251063/

相关文章:

java - Metastore db hive - 另一个实例已经在运行

java - Java中有什么好的动态SQL构建器库吗?

java - 多对一 Hibernate 映射

java - 将 HTTP 响应(Java "Properties"流格式)转换为 NSDictionary

java - 64 位操作系统上 32 位 JVM 的最大 Java 堆大小

java - @JoinColumnS 涉及一对一关系中的 EAGER 获取

php - SQL注入(inject)无法正常工作

Mysql ORDER BY (Column2+Column3) 如果 Column1 为空?

hibernate - HQL在Hibernate中实时转成SQL吗?

spring - 在 jsp 文件中使用 taglib 会抛出 500 错误