Проблеми із запитом під час використання Enum у сутності


83

У сутності запитання у мене є таке:

@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)

Як це виправити?


ви використовуєте користувацький перелік? Чи можете ви оновити документ, щоб відобразити перелік стану?
Gonzalo Garcia Lasurtegui

Відповіді:


154

Я думаю, що вам слід використовувати ваш (повністю кваліфікований) Statusперелік замість буквального значення, тож приблизно так: (за умови, що ваш Statusперелік перебуває в com.myexampleпакеті)

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

А як щодо звичайного JPA2 @Query? Він скаржиться на: Значення атрибута анотації Query.value має бути константним виразом.
Стефан

2
Про яку @Queryанотацію ви говорите?
Piotr Nowicki

2
Це fully qualifiedважливіше, оскільки я думав, що це може бути.
Олександр

6
На стороні: Це не спрацювало, коли перелік був внутрішнім класом сутності. Якщо це не працює для вас, переконайтеся, що перелік - це власний файл!
evandongen

-5

Через 4 роки від початкової посади є певні зрушення. Використовуючи пружини 4 та Hibernate 4, тепер можна «обдурити» Hibernate за допомогою виразу SpEL. Наприклад:

Перелік:

package com.mycompany.enums

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

Ось клас обгортки під назвою 'Filter', який ми передамо методу фільтрації сховища.

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 прив’язує цей вираз до змінних запиту.


Ви не бачите його серед прив'язок змінних, оскільки константа вже підставлена ​​в рядок запиту.
АбуНассар,

-6

Будь ласка, використовуйте властивість нижче в application.properties logging.level.org.hibernate.type.descriptor.sql.BasicBinder = TRACE

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.