2011-02-02 93 views
16

我在Oracle中的表,其中列SC_CUR_CODE是CHAR(3)休眠本地查詢 - CHAR(3)列

當我這樣做:

Query q2 = em.createNativeQuery("select sc_cur_code, sc_amount from sector_costs"); 

    q2.setMaxResults(10); 

    List<Object[]> rs2 = q2.getResultList(); 

    for (Object[] o : rs2) { 
     System.out.println(">>> cur=" + o[0]); 
    } 

我看到cur=Ecur=U,而不是cur=EURcur=USD

o[0]是java.lang.Character中

我怎樣才能得到充分的VALU e EURUSD

回答

34

它看起來像Hibernate讀取類型CHAR(n)的值爲Character。嘗試將它轉換爲VARCHAR(n)

Query q2 = em.createNativeQuery(
    "select cast(sc_cur_code as VARCHAR2(3)), sc_amount from sector_costs"); 

當通過Session接口使用Hibernate,你可以explcitly(通過unwrap()在JPA 2.0還訪問)設置一個類型的結果與addScalar()代替:

Query q2 = em.createNativeQuery(
    "select sc_cur_code, sc_amount from sector_costs"); 
q2.unwrap(SQLQuery.class).addScalar("sc_cur_code", StringType.INSTANCE); 

有在Hibernate JIRA中存在大量未解決的與此問題有關的問題,從HHH-2220開始。

這裏是由Max Rydahl安德森從HHH-2220的言論的解釋:

目前Hibernate支持一種從SQL類型「AUTOMAGIC」映射到Hibernate/Java類型 - 因爲在做很多含糊不清的這樣的映射有時候不符合你實際需要的。

這就是爲什麼我們總是建議使用顯式addScalar或者如果您不希望遍及您的代碼使用Dialect的子類來指定您想要的多個可能映射中的哪一個。

CHAR的問題是最有問題的問題,但它不容易修復 - 我們需要一個registerType(type,from,to,typename)來映射範圍而不是特定的長度......但是即使那麼你可能會碰到映射歧義(例如,有時你想要一個數組,其他時間字符串等)因此,使用.addScalar被推薦用於任何本地sql查詢 - 取決於自動發現總是有風險的,應該只用於最低限度。

如果您在Hibernate映射配置文件中描述了您的本機查詢,那麼您需要爲返回的每個值定義<return-scalar ...>。注意:您必須枚舉所有返回的值,因爲當您明確定義返回類型時,自動發現將被關閉,並且只返回已聲明的列。

<sql-query name="myQuery"> 
    <query-param name="days" type="int" /> 
    <return-scalar column="count" type="int" /> 
    <return-scalar column="section_name" type="string" /> 
    <![CDATA[select count(id) as count, section_name from document where days <= :days]]> 
</sql-query> 
+0

是的,就是這樣。找到這個功能的相關jira問題。 http://opensource.atlassian.com/projects/hibernate/browse/HHH-2304 – Guus 2011-02-02 11:00:57