2012-03-09 149 views
4

我正在使用SQL查詢,然後使用Hibernates的Transformers.aliasToBean()轉換結果。 我的查詢中的一列是枚舉。枚舉失敗了。我該怎麼辦?我應該使用哪種數據類型?我想要超過1個字符將結果轉換爲我的枚舉類型。對於枚舉字段類型,Hibernate SQL轉換失敗

這是如何我的查詢的簡化版本/代碼看起來像(b是表中的枚舉型材):

session.createSQLQuery("select a, b from profiles").setResultTransformer(Transformers.aliasToBean(Profile.class)) 
        .list(); 

例外:expected type: Foo.ProfileStateEnum, actual value: java.lang.Character

+0

你只想使用** Transformers.aliasToBean **或** HQL **會做什麼? – ManuPK 2012-03-09 13:27:19

+0

我正在編寫本機SQL查詢,因此我猜測HQL不夠。 – 2012-03-10 05:11:16

回答

10

假設的Java對應於列b的枚舉類型是Foo.ProfileStateEnum,下面的代碼片段應該適用於您。 (我用Hibernate 4.1.6測試過)

import java.util.Properties; 
import org.hibernate.type.Type; 
import org.hibernate.type.IntegerType; 
import org.hibernate.internal.TypeLocatorImpl.TypeLocatorImpl; 
import org.hibernate.type.TypeResolver.TypeResolver; 
import org.hibernate.type.EnumType; 

Properties params = new Properties(); 
params.put("enumClass", "Foo.ProfileStateEnum"); 
params.put("type", "12"); /*type 12 instructs to use the String representation of enum value*/ 
/*If you are using Hibernate 5.x then try: 
params.put("useNamed", true);*/ 
Type myEnumType = new TypeLocatorImpl(new TypeResolver()).custom(EnumType.class, params); 

List<Profile> profileList= getSession().createSQLQuery("select a as ID, b from profiles") 
      .addScalar("ID", IntegerType.INSTANCE) 
      .addScalar("b", myEnumType) 
      .setResultTransformer(Transformers.aliasToBean(Profile.class)) 
      .list(); 
+0

這絕對看起來很有趣。我會試試看。謝謝。 – 2012-11-29 07:13:19

+0

不工作在休眠5.x.我正在尋找一個快速解決方案,用於休眠5.x. – bavon 2016-06-26 12:54:19

+0

對於休眠5.x嘗試params.put(「useNamed」,true);而不是params.put(「type」,「12」); – gunalmel 2016-08-19 18:07:40

0

讓我們來看看爲什麼你會得到這個例外。

從這個問題很明顯,你已經在你的模型類中使用@Enumerated(EnumType.STRING)註釋字段'b'。所以該字段是枚舉爲您的模型類varchar爲您的數據庫。原生SQL不關心你的模型類,並返回數據庫表中原來的狀態。因此,在您的情況下,您正在使用的SQLQuery將返回String代替'b'而不是ProfileStateEnum類型。但是'b'Profile類中的設置方法需要ProfileStateEnum類型參數。

因此,你得到的異常「預期的類型:Foo.ProfileStateEnum,實際值:java.lang.Character中的」

您可以使用別名來解決這個問題。

我的建議是,用你想要的任何名稱爲你的列別名,併爲你的模型/ dto中的別名創建一個setter方法。

例如,可以將您的列別名爲'enumStr'。

然後將查詢看起來是這樣的: 「選擇A,B爲enumStr從型材

現在,創建在您Profile類的別名setter方法。

(假設枚舉ProfileStateEnum可以具有任何兩個值STATE1STATE2的)

public void setEnumStr(String str){ 
    /*Convert the string to enum and set the field 'b'*/ 
    if(str.equals(ProfileStateEnum.STATE1.toString())){ 
     b = ProfileStateEnum.STATE1; 
    } else { 
     b = ProfileStateEnum.STATE2; 
    } 
} 

現在上變換時,裝定爲別名setEnumStr(String)將被調用,而不是設置器爲字段setB(ProfileStateEnum)和字符串將被轉換並保存爲您想要的類型,無任何例外。

我是Hibernate的初學者,解決方案適用於我。我正在使用PostgreSQL。但我相信它也適用於其他數據庫。