114 Stimmen

Probleme bei der Erstellung einer Abfrage bei Verwendung von Enum in Entity

Ich habe das Folgende in einer Frage Entität:

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

y

@Enumerated(EnumType.STRING)
private Status status;

// usual accessors

Ich erhalte diese Ausnahme:

Beschreibung der Ausnahme: Fehler beim Kompilieren der Abfrage [Question.countApproved: SELECT COUNT(q) FROM Question q WHERE q.status = 'APPROVED' ], Zeile 1, Spalte 47: ungültiges enum equal Ausdruck, kann den enum-Wert von [myCompnay.application.Status] w vom Typ [java.lang.String] . bei org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:501)

Wie kann ich das beheben?

239voto

Piotr Nowicki Punkte 17434

Ich denke, Sie sollten Ihre (voll qualifizierte) Status enum anstelle eines literalen Wertes, also etwa so: (unter der Annahme, dass Ihr Status enum ist in com.myexample Paket)

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

-3voto

Tom Silverman Punkte 574

4 Jahre nach dem ersten Beitrag gibt es einige Entwicklungen. Mit Spring 4 und Hibernate 4 ist es nun möglich, Hibernate mit einem SpEL-Ausdruck zu "überlisten". Zum Beispiel:

Die Aufzählung:

package com.mycompany.enums

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

Hier ist eine Wrapper-Klasse namens "Filter", die wir an die Filtermethode des Repositorys übergeben.

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

 }

Im Repository können wir nun die Klasse Filter als einzigen Parameter verwenden und die Abfrage dazu bringen, das, was wie eine Mischung aus Literalen und SpEL-Ausdrücken aussieht, in ein Statusobjekt zu übersetzen:

Das Endlager:

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

Dies funktioniert perfekt, aber aus irgendeinem seltsamen Grund, den ich noch nicht herausgefunden habe, wenn Sie SQL-Debugging in Hibernate aktivieren und die Binder-Protokollierung einschalten, können Sie nicht sehen, wie Hibernate diesen Ausdruck an Abfragevariablen bindet.

-12voto

Bitte verwenden Sie die folgende Eigenschaft in application.properties

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X