我正在使用SQL查询,然后使用Hibernates的Transformers.aliasToBean()
转换结果。
我的查询中的一列是枚举。这种转变在某种程度上失败了。我该怎么办?我应该使用哪种数据类型?我想要超过1个字符将结果转换为我的枚举类型。
这是我的查询/代码的简化版本的样子( b 是表格配置文件中的枚举):
session.createSQLQuery("select a, b from profiles").setResultTransformer(Transformers.aliasToBean(Profile.class))
.list();
例外:expected type: Foo.ProfileStateEnum, actual value: java.lang.Character
答案 0 :(得分:12)
假设与b列对应的java枚举类型是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();
答案 1 :(得分:1)
我找到了两种方法来实现它。
将org.hibernate.type.CustomType
与org.hibernate.type.EnumType
一起使用(放置EnumType.NAMED
或EnumType.TYPE
,请参见EnumType#interpretParameters
)。如下所示:
Properties parameters = new Properties();
parameters.put(EnumType.ENUM, MyEnum.class.getName());
// boolean or string type of true/false; declare database type
parameters.put(EnumType.NAMED, true);
// string only; declare database type
parameters.put(EnumType.TYPE, String.valueOf(Types.VARCHAR));
EnumType<MyEnum> enumType = new EnumType<>();
enumType.setTypeConfiguration(new TypeConfiguration());
enumType.setParameterValues(parameters);
CustomType customEnumType = new CustomType(enumType);
另一种简单的方法。将org.hibernate.type.StandardBasicTypeTemplate
与org.hibernate.type.descriptor.sql.*TypeDescriptor
一起使用。如下所示:
StandardBasicTypeTemplate<MyEnum> enumType =
new StandardBasicTypeTemplate<>(VarcharTypeDescriptor.INSTANCE,
new EnumJavaTypeDescriptor<>(MyEnum.class));
答案 2 :(得分:0)
让我们看看你为什么会遇到这个例外。
从问题中可以明显看出,您已在模型类中使用了{em>&#39; b&#39; 字段的@Enumerated(EnumType.STRING)
注释。因此,该字段是您的模型类的枚举和数据库的 varchar 。本机SQL不关心您的模型类,并返回数据库表中的内容。因此,在您的情况下,您使用的SQLQuery
将为&#39; b&#39; 而不是String
类型返回ProfileStateEnum
。但是,Profile
类中&#39; b&#39; 的setter方法采用ProfileStateEnum
类型参数。
因此你得到异常&#34;期望类型:Foo.ProfileStateEnum,实际值:java.lang.Character&#34;
您可以使用别名来解决问题。
我的建议是,使用您想要的任何名称为您的列添加别名,并在模型/ dto中为该别名创建一个setter方法。
例如,允许您将列别名为&#39; enumStr&#39;。
然后您的查询将如下所示:&#34; 从个人资料中选择a,b作为enumStr &#34;
现在,在Profile
类中为该别名创建一个setter方法。
(假设枚举ProfileStateEnum
可以包含STATE1
和STATE2
两个值中的任何一个
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)
的setter而不是字段setB(ProfileStateEnum)
的setter,字符串将被转换并保存到您想要的类型,没有任何例外。
我是Hibernate的初学者,解决方案对我有用。我正在使用PostgreSQL。但我相信它也适用于其他数据库。