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

86

В сущности вопроса у меня есть следующее:

@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: недопустимое выражение enum equal, невозможно сравнить значение перечисления типа [myCompnay.application.Status]со значением типа, отличным от перечисления [java.lang.String]. в org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy (EntityManagerSetupImpl.java:501)

Как это исправить?

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

Ответы:

160

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

@NamedQuery(name = "Question.allApproved", 
            query = "SELECT q 
                     FROM Question q 
                     WHERE q.status = com.myexample.Status.APPROVED").
Петр Новицкий
источник
А как насчет обычного @Query в формате JPA2? Он жалуется на: значение атрибута аннотации Query.value должно быть постоянным выражением.
Стефан
2
О какой @Queryаннотации вы говорите?
Петр Новицки
2
Это fully qualifiedболее важно, как я думал.
Александр
9
Замечание: это не сработало, когда перечисление было внутренним классом сущности. Если это не сработает, убедитесь, что перечисление - это собственный файл!
evandongen
@evandongen любое решение, если enum является внутренним классом?
Raja aar
-5

Через 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 связывает это выражение с переменными запроса.

Том Сильверман
источник
Вы не видите его среди привязок переменных, потому что константа уже была подставлена ​​в строку запроса.
AbuNassar
-6

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

Сантош Чоудхари
источник