2012-08-17 65 views
10

在我的Spring/Hibernate/JPA應用程序中,我使用了很多命名查詢,當我在其中一個查詢中遇到錯字時,在我的應用程序啓動日誌文件中看到與下面類似的錯誤。如何讓hibernate打印出命名查詢有什麼問題?

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 

如何配置hibernate打印指定查詢的錯誤而不僅僅是指定的查詢有錯誤?

UPDATE例如,JPA查詢SELECT f FROM Foo WHERE f.v := true將失敗,並且hibernate抱怨查詢無效。 Hibernate甚至沒有試圖從它生成SQL,查詢是不正確的JPQL。我想知道的是如何讓hibernate說查詢是錯誤的,因爲:=被用來代替=?不確定這是否是一個可以在休眠狀態下打開的設置。

回答

0

您可以嘗試通過設置

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

然後log4j的加適量日誌級別以顯示org.hibernate作爲的DEBUG或者TRACE級別的日誌打印HSQL *這裏

更多信息: http://docs.jboss.org/hibernate/core/3.5/reference/en/html/session-configuration.html#configuration-logging

+2

顯示sql會打印出生成的sql,這不是問題,問題是JPQL查詢有問題,hibernate無法解析它,所以我試圖找出如何獲得hibernate來解釋什麼是錯誤的用JPQL查詢。 – ams 2012-08-17 11:12:14

+0

是的,我知道,但看看HSQL是唯一可以說明這一點的方法。該錯誤是從SessionFactoryImpl創建的。如果您查看該類中checkNamedQueries()的實現,它已經添加了errors.put(queryName,e);查詢名稱爲「FindAllCompanyFileTypes」,您的案例中的e爲空。 – Vivek 2012-08-17 11:34:48

0

如果我猜你在問什麼,我不認爲它是冬眠,可以告訴你什麼是錯的。我獲得成功的唯一方式是相當痛苦的,但至少它是有效的!

所以你需要數據庫本身告訴你查詢有什麼問題。要做到這一點,你可以像上面描述的那樣從休眠狀態啓用sql輸出。然後你通過你最喜歡的工具連接到數據庫:squirrelSQL,toad,eclipse-plugin等。現在,如果你的sql中沒有參數,那麼你只需剪切並粘貼到那裏,執行sql,它應該可以幫助你調試。

如果你有參數,過程是一樣的,只是更繁瑣!但是,一旦你有了SQL,數據庫就會告訴你它不喜歡什麼。在大多數情況下,一旦你知道這一點,就會清楚你需要在休眠方面改變什麼。不時有時它可能是一個謎,但大多數這些情況都記錄在這裏!

+0

請看我對問題的更新。 – ams 2012-08-17 14:06:11

7

Hibernate自定義查詢加載器的東東位於org.hibernate.loader.custom.sql(對於Hibernate 3而言似乎是Hibernate 4 too)。如果使用log4j,則只需要設置此包its own category以獲取打印的日誌(我建議您使用文件appender,因爲如果使用控制檯appender,以後的錯誤日誌可能會覆蓋您感興趣的內容)。

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

假設你的根記錄顯示在文件中的每個錯誤,這就是你得到的,而查詢加載錯誤輸出:

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) 

該異常被提出的加載時間,但你也可以有在執行代碼時查詢錯誤。在這種情況下,會拋出一個HibernateException或類似的東西,您可以稍後檢查。對於缺少冒號的情況下,它實際上是由AbstractQueryImpl類引發的IllegalArgumentException

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

我工作的一個類似的問題,我發現,如果你使用Spring數據JPA,您可以在使用@Query DAO接口,而不是實體對象中的@NamedQuery,您會得到更詳細的錯誤消息。因此,而不是:

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

你會說

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

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

中採用相同的查詢語言和表達方式,但無論實施的怪癖,提供了一個更富於表現力的錯誤消息。