2012-03-09 29 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。但我相信它也适用于其他数据库。