2015-12-13 14 views
9

Chciałbym wykonać natywne zapytanie SQL przez JPA 2.0 z Hibernate w wersji 4.2.21 na systemie bazy danych Postgres 9.4.Różnice w wykonywaniu zapytań przez Hibernate i PostgreSQL prowadzące do PSQLException

Zasadniczo, zgodnie z moim najnowszym post na stackoverflow, staram się umieścić dużą liczbę obiektów/rekordów w wiadrach "temporalnych".

Konfiguracja można uprościć do następującej konfiguracji zawierającej tabela „MyObject” z pola ID i dany znacznik czasu:

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

Mój kawałek kodu, który powinien wykonać kwerendy jest to jedno:

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 

wykonywanie kwerendy z datą próbki poprzez pgAdmin3 zwraca wynik, jak oczekiwano.

Jednakże jeśli próbuję wykonać takie samo zapytanie poprzez Hibernate jako native zapytania nie powiedzie się z następującym wyjątkiem:

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 

Wyjątek ten wydaje się ważne i self-wyjaśniając jednak, dlaczego mogę wykonać to samo zapytanie przez PgAdmin3? Czy parser Hibernuj SQL jest bardziej restrykcyjny niż pgAdmin3, czy też kompensuje jakiś błąd?

W jaki sposób można sformułować moje zapytanie SQL, aby było możliwe do wykonania przez Hibernate?

EDIT:

Z jakiegoś powodu następujących instrukcji SQL (z wyraźną sub-select) działa poprzez PgAdmin3 jak również poprzez 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 

Ale to nadal nie jest odpowiedź na pytanie dla poprzedniego zapytania w podanym fragmencie kodu.

Odpowiedz

5

Ta kwerenda powinny działać również bez podzapytaniu:

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

Powodem Podejrzewam: Hibernate wykorzystuje prepared statements i dwa występujące :startDate są przekazywane jako dwa parametrów. W ten sposób, Postgres nie można zakładać, że oba wyrażenia (na liście SELECT iw GROUP BY) są takie same ...

Demonstracja z równoważnej SQL command PREPARE to działa:

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

Chociaż nie:

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

.. i podnosi ten sam wyjątek, co Ty.

Możesz uniknąć problemu a priori z zapytaniem, które zasugerowałem.

pokrewne:

+0

Dzięki za sugestie. Świetna odpowiedź! – rzo

Powiązane problemy