Hibernate SQL transformation fails for Enum field type

喜你入骨 提交于 2019-11-27 02:52:07

问题


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


回答1:


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();



回答2:


Let's see why you are getting this exception.

From the question it is obvious that you have used @Enumerated(EnumType.STRING) annotation for the field 'b' in you model class. So the field is an enum for your model class and a varchar for your database. Native SQL is not concerned about you model class and returns what ever is there in the database table as it is. So in your case, the SQLQuery you are using will return a String for 'b' instead of a ProfileStateEnum type. But your setter method for 'b' in the Profile class takes a ProfileStateEnum type argument.

Thus you get the exception "expected type: Foo.ProfileStateEnum, actual value: java.lang.Character"

You can use Aliasing to solve the problem.

What I suggest is, alias your column with any name you want and create a setter method for that alias in your model/dto.

For example, lets alias your column as 'enumStr'.

Then your query will look like this : "select a, b as enumStr from profiles"

Now, create a setter method for that alias in the your Profile class.

(Assuming that the enum ProfileStateEnum can have any of the two values STATE1 and 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;
    }
}

Now on transforming, the setter for the alias setEnumStr(String) will be invoked instead of setter for the field setB(ProfileStateEnum) and the string will be converted and saved to the type you want without any exceptions.

I am a beginner in Hibernate and the solution worked for me. I am using PostgreSQL. But I believe it works for other databases too.



来源:https://stackoverflow.com/questions/9633337/hibernate-sql-transformation-fails-for-enum-field-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!