Значение параметра не соответствует ожидаемому типу

у меня есть перечисление со списком состояний (например)

enum State
{
   UP,
   DOWN,
   RETRY
};

столбец в моей базе данных имеет тип перечисление. Когда я пытаюсь выполнить запрос Hibernate, установив параметр в запросе с помощью setParameter("keyword", State.RETRY);, Я получаю ошибку

значение параметра [повтор] не соответствует ожидаемому типу [пакет.имя.Состояние (n/a)]

на моем сервере Glassfish 4.1.войдите в мой домен. Я использую Hibernate 4.3.6.

глядя на исходный код для Hibernate, я вижу, что ошибка возникает из-за строки 958-960 на org.hibernate.jpa.spi.BaseQueryImpl:

private static boolean isValidBindValue(Class expectedType, Object value, TemporalType temporalType) {
        if ( expectedType.isInstance( value ) ) {
            return true;
        }
...
return false;
}

isValidBindValue возвращает false и, таким образом, я получаю сообщение.

он выводит String эквивалентно enum значение из-за этой строки:

String.format("Parameter value [%s] did not match expected type [%s (%s)]",
               bind,
               parameterType.getName(),
               extractName( temporalType )
             )

на bind объект неявно преобразуется в строковое значение, вызывая toString метод Object представляет enum State.RETRY.

так как я могу я убедить гибернации, что State.RETRY пример State?

похоже, что Hibernate обновлен до спецификации JPA 2.1, которая более строгая в этом коммите с апреля 2013 года:

https://github.com/hibernate/hibernate-orm/commit/84520cd6e36e9207c41528cf9311cae905a86425

сущность аннотируется следующим образом:

@Basic(optional = false)
@Column(name = "state")
@Enumerated(EnumType.String)
private State state;

Edit:

мой RetryState тип загрузки EarLibClassLoader. Тогда как Query загружается по URLClassLoader и EntityManager загружается другим загрузчиком класса.

2 ответов


Я думаю, основная проблема заключается в том, что вы пытаетесь использовать тип данных enum на стороне базы данных. Это не рекомендуется, потому что часто требуется проприетарный тип перечисления, который может не поддерживаться реализацией JPA (например, Hibernate). См.ответ по аналогичному вопросу для некоторых деталей.

далее с аннотацией

@Enumerated(EnumType.String)

вы говорите, что вы явно хотите, чтобы значение было сохранено в строке in база данных. Я ожидал бы, что это не удастся, если реальный тип столбца-некоторое перечисление. Возможно, изменения кода Hibernate пытаются предотвратить эти проблемы, заставляя вас использовать либо тип varchar или целое столбцы.

возможные решения:

A)

используйте столбец varchar с @Enumerated(EnumType.String) или столбец int с @Enumerated

B)

вы можете попробовать укажите столбец перечисления через аннотацию

@Basic(optional = false)
@Column(name = "state", columnDefinition = "enum('UP','DOWN','RETRY')")
@Enumerated(EnumType.String)
private State state;

C)

вы можете попытаться указать свой класс перечисления через файл сопоставления XML hibernate:

<property name="type" column="type" not-null="true">
    <type name="org.hibernate.type.EnumType">
        <param name="enumClass">package.name.State</param>
        <param name="type">12</param>
        <!-- 12 is java.sql.Types.VARCHAR -->
    </type> 
</property>

Читайте также:


Это было исправлено путем размещения классов с аннотациями JPA и классами перечисления в домен-dir/lib / applib