Проблемы с выполнением запроса при использовании Enum в сущности

У меня есть следующее в объекте Question:

@NamedQuery(name = "Question.allApproved",
    query = "SELECT q FROM Question q WHERE q.status = 'APPROVED'")

и

@Enumerated(EnumType.STRING)
private Status status;

// usual accessors

Я получаю это исключение:

Описание исключения: Ошибка при компиляции запроса [Question.countApproved: SELECT COUNT(q) FROM Question q WHERE q.status = 'APPROVED'], строка 1, столбец 47: недопустимое выражение равенства перечисления, невозможно сравнить значение перечисления типа [myCompnay.application.Status] со значением типа [java.lang.String], отличным от перечисления. в org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:501)

Как я могу это исправить?


person LuckyLuke    schedule 21.11.2011    source источник
comment
вы используете собственное перечисление? Можете ли вы обновить документ, чтобы отобразить перечисление Status?   -  person Gonzalo Garcia Lasurtegui    schedule 21.11.2011


Ответы (3)


Я думаю, вы должны использовать свое (полное) перечисление Status вместо буквального значения, так что-то вроде этого: (при условии, что ваше перечисление Status находится в пакете com.myexample)

@NamedQuery(name = "Question.allApproved", 
            query = "SELECT q 
                     FROM Question q 
                     WHERE q.status = com.myexample.Status.APPROVED").
person Piotr Nowicki    schedule 21.11.2011
comment
Как насчет обычного @Query JPA2? Он жалуется: значение атрибута аннотации Query.value должно быть постоянным выражением. - person Stephane; 21.09.2014
comment
О какой @Query аннотации вы говорите? - person Piotr Nowicki; 21.09.2014
comment
Это fully qualified важнее, чем я думал. - person alexander; 12.08.2015
comment
На заметку: это не сработало, когда перечисление было внутренним классом объекта. Если это не работает для вас, убедитесь, что перечисление является собственным файлом! - person evandongen; 10.10.2019
comment
@evandongen любое решение, если перечисление является внутренним классом? - person Raja aar; 05.01.2021
comment
@Rajaaar, к сожалению, не было - person evandongen; 06.01.2021
comment
хорошо, к счастью, мой код достаточно гибок, чтобы отправлять список перечислений при вызове метода репо. Например, @Query(SELECT a from ‹yourEnitity› a where a.Status IN (:statuses)) myRepo.someMethodName(@Param(statuses) List‹enum class› statuss) Это сработало для меня. в любом случае спасибо за ответ @evandongen - person Raja aar; 06.01.2021
comment
@evandongen, посмотрите этот ответ из другого потока, чтобы разобраться с внутренними классами: stackoverflow.com/a/48393602/3232174 - person GB11; 21.02.2021

Прошло 4 года с момента первоначального поста, есть некоторые изменения. Используя Spring 4 и Hibernate 4, теперь можно «обмануть» Hibernate, используя выражение SpEL. Например:

Перечисление:

package com.mycompany.enums

public enum Status {
    INITIAL, PENDING, REJECTED, APPROVED, SHIPPED, DELIVERED, COMPLETE;
}

Вот класс-оболочка под названием «Фильтр», который мы передадим методу фильтрации репозитория.

package com.mycompany.enums

public class Filter implements Serializable {

    /** The id of the filtered item */
    private Integer id;
    /** The status of the filtered item */
    private Status status;
    // more filter criteria here...

    // getters, setters, equals(), hashCode() - omitted for brevity

    /**
     * Returns the name of the status constant or null if the status is null. This is used in the repositories to filter
     * queries by the status using a the SPEL (T) expression, taking advantage of the status qualified name. For example:
     * {@code :#{T(com.mycompany.enums.Status).#filter.statusName}}
     *
     * @return the status constant name or null if the status is null
     */
    public String getStatusName() {
        return null == status ? status : status.name();
    }

 }

Наконец, в репозитории теперь мы можем использовать класс Filter в качестве единственного параметра и заставить запрос переводить то, что кажется смесью литералов и выражений SpEL, в объект Status:

Репозиторий:

package com.mycompany.repository

@Repository
public interface OrderRepository extends CrudRepository<Order, Integer> {

    @Query("SELECT o from Order o "
            + "WHERE o.id = COALESCE(:#{#filter.id},o.id) "
            + "AND o.status = COALESCE(:#{T(com.mycompany.enums.Status).#filter.statusName},o.status)")
    public List<Order> getFilteredOrders(@Param(value = "filter") Filter filter);
}

Это работает отлично, но по какой-то странной причине, которую я еще не понял, если вы включите отладку SQL в Hibernate и включите ведение журнала связывателя, вы не сможете увидеть, как Hibernate привязывает это выражение к переменным запроса.

person Tom Silverman    schedule 30.04.2016
comment
Вы не видите его среди привязок переменных, потому что константа уже была подставлена ​​в строку запроса. - person AbuNassar; 18.12.2018

Пожалуйста, используйте свойство ниже в application.properties logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

person Santosh choudhary    schedule 28.01.2017