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

我在一个问题实体中有以下内容:

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

还有

@Enumerated(EnumType.STRING)
private Status status;


// usual accessors

我得到了一个例外:

异常说明: 编译查询时出错 [ question.count 已批准: SELECT COUNT(q) FROM Question q WHERE q.status = 'APPROVED'] ,第1行,第47列: 无效枚举相等 表达式,不能比较类型的枚举值 具有非枚举值的 [myCompnay.application.Status] 类型 [java.lang.String] 部署(EntityManagerSetupImp.java: 501)

我该怎么补救?

84367 次浏览

I think you should use your (fully qualified) Status enum instead of literal value, so something like this: (assuming your Status enum is in com.myexample package)

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

4 years since the initial post, there are some developments. Using spring 4 and Hibernate 4 it's now possible to 'trick' Hibernate using a SpEL expression. For example:

The enum:

package com.mycompany.enums


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

Here's a wrapper class called 'Filter' which we'll pass to the repository filtering method.

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


}

Finally, in the repository, we can now use the Filter class as the single parameter and make the query translate what appears to be a mixture of literals and SpEL expressions to a Status object:

The repository:

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

This works perfectly, but for some odd reason I haven't figured out yet, if you enable SQL debugging in Hibernate and turn on the binder logging, you'll not be able to see Hibernate binding this expression to query variables.

Please use below property in application.properties

logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE