2015-12-13 14 views
9

Vorrei eseguire una query SQL nativa tramite JPA 2.0 con Hibernate nella versione 4.2.21 su un sistema di database Postgres 9.4.Differenza nell'esecuzione della query tramite Hibernate e PostgreSQL che portano a PSQLException

Fondamentalmente, in base al mio ultimo post su stackoverflow, provo a inserire un numero elevato di oggetti/record in bucket "temporali".

La configurazione può essere semplificata la seguente configurazione contenente una tabella "MyObject" con un campo id e una data timestamp:

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

mio pezzo di codice, che deve eseguire la query è questa:

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 

che esegue la query con una data di esempio tramite pgAdmin3 restituisce il risultato come previsto.

Tuttavia, se provo ad eseguire la stessa query tramite Hibernate come una query nativa non riesce con la seguente eccezione:

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 

Questa eccezione sembra valido e autoesplicativo, ma perché posso eseguire la stessa query tramite PgAdmin3? Il parser Hibernate SQL è più rigido di pgAdmin3 o compensa qualche errore?

Quindi, come può essere formulata la mia query SQL per renderla eseguibile tramite Hibernate?

EDIT:

Per qualche ragione la seguente istruzione SQL (con esplicito sub-select) funziona tramite pgAdmin3, così come tramite 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 

Ma questo ancora non risponde alla domanda per la query precedente nel frammento di codice specificato.

risposta

5

Questa query dovrebbe funzionare così, senza sottointerrogazione:

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;

Il motivo ho il sospetto: Hibernate usa prepared statements e le due occorrenze di :startDate vengono passati come due parametri. In questo modo, Postgres non può assumere che le due espressioni (nella lista SELECT e in GROUP BY) sono gli stessi ...

Dimostrare con l'equivalente SQL command PREPARE, questo funziona:

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;

Anche se questo non lo fa:

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;

.. e solleva la stessa eccezione mostrata.

È possibile evitare il problema a priori con la query che ho suggerito.

correlati:

+0

Grazie per i vostri suggerimenti. Bella risposta! – rzo

Problemi correlati