Преобразование Hibernate SQL не выполняется для типа поля Enum - PullRequest
7 голосов
/ 09 марта 2012

Я использую запрос SQL, а затем преобразовываю результат с помощью Transformers.aliasToBean() в Hibernates. Один из столбцов в моем запросе - enum. Преобразование так или иначе терпит неудачу для перечисления. Что я должен делать? Какой тип данных я должен использовать? Я хочу, чтобы более одного символа преобразовало результат в мой тип enum.

Вот так выглядит упрощенная версия моего запроса / кода ( b - это перечисление в профилях таблицы ):

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

Исключение: expected type: Foo.ProfileStateEnum, actual value: java.lang.Character

Ответы [ 2 ]

12 голосов
/ 29 ноября 2012

Предполагая, что типом перечисления 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 голосов
/ 14 ноября 2016

Давайте посмотрим, почему вы получаете это исключение.

Из вопроса очевидно, что вы использовали @Enumerated(EnumType.STRING) аннотацию для поля 'b' у тебя модельный класс.Таким образом, поле представляет собой перечисление для вашей модели класса и varchar для вашей базы данных .Собственный SQL не заботится о вашем классе модели и возвращает то, что есть в таблице базы данных, как есть.Таким образом, в вашем случае SQLQuery, который вы используете, вернет String для 'b' вместо типа ProfileStateEnum.Но ваш метод установки для 'b' в классе Profile принимает аргумент типа ProfileStateEnum.

Таким образом, вы получите исключение "ожидаемый тип: Foo.ProfileStateEnum, фактическое значение: java.lang.Character"

Вы можете использовать Aliasing для решенияпроблема.

Я предлагаю создать псевдоним вашего столбца с любым именем и создать метод установки для этого псевдонима в вашей модели / dto.

Например, пусть псевдоним вашего столбца будет 'enumStr'.

Тогда ваш запрос будет выглядеть так: " выберите a, b в качестве enumStr из профилей "

Теперь создайте метод установки для этого псевдонима в вашем классе Profile.

(Предполагая, что перечисление 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) будет вызываться вместо установщика для поля setB(ProfileStateEnum), и строка будет преобразована и сохранена в нужный вам тип без каких-либо исключений.

Я новичок в Hibernate, и решение сработало для меня.Я использую PostgreSQL.Но я считаю, что это работает и для других баз данных.

...