Проблемы с созданием запроса при использовании 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)
Как это исправить?
Ответы
Ответ 1
Я думаю, вы должны использовать свой (полностью квалифицированный) Status
enum вместо литерального значения, так что примерно так: (если ваш Status
enum находится в пакете com.myexample
)
@NamedQuery(name = "Question.allApproved",
query = "SELECT q
FROM Question q
WHERE q.status = com.myexample.Status.APPROVED").
Ответ 2
Используйте свойство ниже в application.properties
logging.level.org.hibernate.type.descriptor.sql.BasicBinder = TRACE
Ответ 3
Через 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 привязывает это выражение к запросам переменных.