2012-08-17 7 views
10

Nella mia applicazione Spring/Hibernate/JPA utilizzo molte query con nome e quando ho un errore di battitura in una di queste query vedo errori nel file di registro di avvio dell'applicazione simile a quello riportato di seguito.Come ottenere l'ibernazione per stampare cosa c'è di sbagliato in una query con nome?

Caused by: org.hibernate.HibernateException: Errors in named queries: FindAllCompanyFileTypes 
    at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:426) 
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1872) 
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:906) 
    ... 70 more 

Come si configura Hibernate di stampare ciò che è sbagliato con la query di nome e non solo la query denominata presenta un errore?

UPDATE per esempio la query JPA SELECT f FROM Foo WHERE f.v := true non riuscirà con la sospensione che si lamenta che la query non è valida. Hibernate non ha nemmeno provato a generare SQL da esso, la query non è corretta JPQL. Quello che voglio sapere è come ottenere l'ibernazione per dire che la query è sbagliata perché: = è stato usato al posto di =? non sono sicuro se questa è un'impostazione che può essere attivata in ibernazione o meno.

risposta

0

Si può provare a stampare il HSQL impostando il

<property name="show_sql">true</property> 

quindi aggiungere livelli di log corretti in log4j per visualizzare la registrazione di debug o livello di traccia per org.hibernate *

maggiori informazioni qui.: http://docs.jboss.org/hibernate/core/3.5/reference/en/html/session-configuration.html#configuration-logging

+2

Mostra sql stamperà lo sql generato, che non è il problema il problema è che la query JPQL ha un problema, l'ibernazione non può analizzarlo, quindi sto cercando di scoprire come ottenere l'ibernazione per spiegare cosa è sbagliato con una query JPQL. – ams

+0

Sì, lo so, ma guardare l'HSQL è l'unico modo per dirlo. L'errore viene creato da SessionFactoryImpl. Se si guarda all'implementazione di checkNamedQueries() in quella classe è già aggiunta errors.put (queryName, e); Il nome della query è "FindAllCompanyFileTypes" ed e nel tuo caso è vuoto. – Vivek

0

Se faccio un'ipotesi su quello che chiedi, non penso che sia in ibernazione che possa dirti cosa c'è che non va. L'unico modo in cui ho avuto successo con questo è piuttosto doloroso, ma almeno funziona!

Quindi è necessario il database stesso per dirti cosa c'è di sbagliato nella query. Per fare ciò abilita l'output SQL dalla sospensione come descritto sopra. Poi ti connetti al DB tramite il tuo strumento preferito: squirrelSQL, rospo, eclipse-plugin, ecc. Ora se non hai parametri nel tuo sql, devi solo tagliare e incollare lì, eseguire sql e dovrebbe aiutarti debug.

Se si dispone di parametri, il processo è lo stesso, solo il modo più noioso! Tuttavia, una volta che hai SQL ok, il database dovrebbe dirti cosa non piace. Nella maggior parte dei casi, una volta compreso questo, sarà chiaro che cosa è necessario modificare sul lato di ibernazione. Ogni tanto però può essere un mistero, ma la maggior parte di questi casi è documentata qui!

+0

per favore vedi il mio aggiornamento della domanda. – ams

7

L'ibernazione del caricatore di query personalizzato si trova in org.hibernate.loader.custom.sql (per Hibernate 3 e sembra che sia Hibernate 4 too). Se si utilizza log4j, è solo questione di impostare questo pacchetto its own category per ottenere la stampa dei registri (ti consiglio di usare l'appender di file perché i log degli errori successivi possono sovrapporsi a quelli che ti interessano se si utilizza l'appender della console).

<category name="org.hibernate.loader.custom.sql" additivity="false"> 
    <priority value="trace" /> 
    <appender-ref ref="fileAppender" /> 
</category> 

Supponendo tuoi Logger visualizza radice ogni errore nel file di, che è l'output che si ottiene per un errore durante interrogazione carico:

17:27:18,348 TRACE SQLCustomQuery:85 -  starting processing of sql query [SELECT equipment.*, det.* 
     FROM tdetectable_equipment equipment JOIN 
     tdetectable det 
     ON det.id = equipment.id_detectable 
     WHERE 
     equipment.id_detectable=det.id and det.active=1 and 
     equipment.id_warehouse_container = :_Id] 
17:27:18,358 TRACE SQLCustomQuery:85 -  starting processing of sql query [select line.* from tpacking_slip_line line join tpacking_slip slip on line.id_packing_slip = slip.id where line.id_detectable = :detectableId and line.id_related_packing_slip_line is null and slip.`type`= :slipType order by slip.date desc;] 
17:27:18,359 TRACE SQLQueryReturnProcessor:387 -  mapping alias [line] to entity-suffix [0_] 
17:27:18,364 TRACE SQLCustomQuery:85 -  starting processing of sql query [select res.* from tdetectable det join tpacking_slip_line line on det.id=line.id_detectable and line.id_related_packing_slip_line is null join tpacking_slip slip on line.id_packing_slip = slip.id and slip.`type`='OUT' join vreservation res on slip.id_reservation=res.id where det.id in (:detIds) group by(res.id) order by count(res.id) desc;] 
17:27:18,365 TRACE SQLQueryReturnProcessor:387 -  mapping alias [res] to entity-suffix [0_] 
17:27:18,368 ERROR SessionFactoryImpl:424 -  Error in named query: equipmentWarehouseQuery 
org.hibernate.MappingException: Unknown collection role: com.mycompany.model.container.Container.detectables 
    at org.hibernate.impl.SessionFactoryImpl.getCollectionPersister(SessionFactoryImpl.java:701) 
    at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.addCollection(SQLQueryReturnProcessor.java:393) 
    at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.processCollectionReturn(SQLQueryReturnProcessor.java:428) 
    at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.processReturn(SQLQueryReturnProcessor.java:358) 
    at org.hibernate.loader.custom.sql.SQLQueryReturnProcessor.process(SQLQueryReturnProcessor.java:171) 
    at org.hibernate.loader.custom.sql.SQLCustomQuery.<init>(SQLCustomQuery.java:87) 
    at org.hibernate.engine.query.NativeSQLQueryPlan.<init>(NativeSQLQueryPlan.java:67) 
    at org.hibernate.engine.query.QueryPlanCache.getNativeSQLQueryPlan(QueryPlanCache.java:166) 
    at org.hibernate.impl.SessionFactoryImpl.checkNamedQueries(SessionFactoryImpl.java:589) 
    at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:413) 
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1872) 
    at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.java:863) 
    at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:782) 
    at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:188) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1541) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1479) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521) 

Tale eccezione viene sollevata al momento del caricamento, ma si può anche avere si verificano errori durante l'esecuzione del codice. In tal caso viene lanciato uno HibernateException o simile, che è possibile ispezionare in seguito.Per il caso di due punti obbligatori in realtà è un IllegalArgumentException lanciata da AbstractQueryImpl classe:

java.lang.IllegalArgumentException: No positional parameters in query: SELECT equipment.*, det.* 
     FROM tdetectable_equipment equipment JOIN 
     tdetectable det 
     ON det.id = equipment.id_detectable 
     WHERE 
     equipment.id_detectable=det.id and det.active=1 and 
     equipment.id_container = _Id 
1

stavo lavorando su un problema simile e ho scoperto che, se si sta utilizzando primavera dati JPA, è possibile utilizzare @query in l'interfaccia DAO invece di @NamedQuery nell'oggetto entità e ottieni un messaggio di errore molto più dettagliato. Così, invece di:

@Entity 
@Table 
@NamedQueries({@NamedQuery(name="MyEntity.myQuery" query="select blah blah blah")}) 
public class MyEntity 
{ 
... 
} 

direste

@Entity 
@Table 
public class MyEntity 
{ 
... 
} 

public interface MyEntityDao 
    extends JpaRepository... 
{ 
    @Query("select blah blah blah") 
    MyEntity findByMyQuery(); 
} 

Questo utilizza lo stesso linguaggio di query e le espressioni, ma, per qualsiasi capriccio di implementazione, fornisce un messaggio di errore molto più espressivo.

Problemi correlati