Problems with making a query when using Enum in entity

JavaJpaJakarta EeJpql

Java Problem Overview


I have the following in a Question entity:

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

and

@Enumerated(EnumType.STRING)
private Status status;

// usual accessors

I am getting this exception:

> Exception Description: Error compiling the query > [Question.countApproved: SELECT COUNT(q) FROM Question q WHERE q.status = 'APPROVED'], line 1, column 47: invalid enum equal > expression, cannot compare enum value of type > [myCompnay.application.Status] with a non enum value > of type [java.lang.String]. at > org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:501)

How do I fix this?

Java Solutions


Solution 1 - Java

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").

Solution 2 - Java

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.

Solution 3 - Java

Please use below property in application.properties logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLuckyLukeView Question on Stackoverflow
Solution 1 - JavaPiotr NowickiView Answer on Stackoverflow
Solution 2 - JavaTom SilvermanView Answer on Stackoverflow
Solution 3 - JavaSantosh choudharyView Answer on Stackoverflow