在实体中使用Enum时进行查询的问题


83

我在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列:无效的枚举等于表达式时出错,无法将type的enum值与type [myCompnay.application.Status]的非enum值进行比较[java.lang.String]。在org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:501)

我该如何解决?


您正在使用自定义枚举吗?您可以更新文档以显示状态枚举吗?
贡萨洛·加西亚·拉苏特吉

Answers:


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的值必须是一个常量表达式。
Stephane 2014年

2
@Query您在说什么注释?
Piotr Nowicki 2014年

2
fully qualified正如我认为的那样,这更重要。
亚历山大

6
附带说明:当枚举是实体的内部类时,它不起作用。如果这对您不起作用,请确保枚举是它自己的文件!
evandongen

-5

自最初职位以来的4年中,出现了一些发展。使用spring 4和Hibernate 4,现在可以使用SpEL表达式来“欺骗” Hibernate。例如:

枚举:

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);
}

这可以很好地工作,但是由于一些奇怪的原因,我还没有弄清楚,如果您在Hibernate中启用SQL调试并打开绑定程序日志记录,您将无法看到Hibernate将此表达式绑定到查询变量。


您不会在变量绑定中看到它,因为常量已被替换为查询字符串。
AbuNassar

-6

请在application.properties logging.level.org.hibernate.type.descriptor.sql.BasicBinder = TRACE中使用以下属性

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.