Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate SQL transformation fails for Enum field type

I am using a SQL query and then transforming the result using Hibernates's Transformers.aliasToBean(). One of the columns in my query is an enum. The transformation somehow fails for the enum. What should I do? Which datatype should I use? I want more than 1 character to transform the result into my enum type.

This is how the simplified version of my query/code looks like (b is an enum in the table profiles):

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

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

like image 796
TJ- Avatar asked Mar 09 '12 11:03

TJ-


2 Answers

Assuming that the java enum type that corresponds to column b is Foo.ProfileStateEnum, the following code snippet should work for you. (I tested with 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();
like image 121
gunalmel Avatar answered Nov 02 '22 20:11

gunalmel


I found two ways to achieve it.

  1. Use org.hibernate.type.CustomType with org.hibernate.type.EnumType(put either EnumType.NAMED or EnumType.TYPE, see EnumType#interpretParameters). Like below:

    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);
    
  2. Another simple way. Use org.hibernate.type.StandardBasicTypeTemplate with org.hibernate.type.descriptor.sql.*TypeDescriptor. Like below:

    StandardBasicTypeTemplate<MyEnum> enumType =
            new StandardBasicTypeTemplate<>(VarcharTypeDescriptor.INSTANCE,
                    new EnumJavaTypeDescriptor<>(MyEnum.class));
    
like image 38
xmcx Avatar answered Nov 02 '22 21:11

xmcx