Probleme beim Erstellen einer Abfrage bei Verwendung von Enum in Entity

86

Ich habe Folgendes in einer Frageentität:

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

und

@Enumerated(EnumType.STRING)
private Status status;

// usual accessors

Ich bekomme diese Ausnahme:

Ausnahme Beschreibung: Fehler beim Kompilieren der Abfrage [Question.countApproved: SELECT COUNT(q) FROM Question q WHERE q.status = 'APPROVED'], Zeile 1, Spalte 47: Ungültiger Enum-Equal-Ausdruck, Enum-Wert vom Typ kann nicht [myCompnay.application.Status]mit einem Nicht-Enum-Wert vom Typ verglichen werden [java.lang.String]. at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy (EntityManagerSetupImpl.java:501)

Wie behebe ich das?

Lucky Luke
quelle
Verwenden Sie eine benutzerdefinierte Aufzählung? Können Sie das Dokument aktualisieren, um die Statusaufzählung anzuzeigen?
Gonzalo Garcia Lasurtegui

Antworten:

156

Ich denke, Sie sollten Ihre (voll qualifizierte) StatusAufzählung anstelle des wörtlichen Werts verwenden, also ungefähr so: (vorausgesetzt, Ihre StatusAufzählung ist im com.myexamplePaket enthalten)

@NamedQuery(name = "Question.allApproved", 
            query = "SELECT q 
                     FROM Question q 
                     WHERE q.status = com.myexample.Status.APPROVED").
Piotr Nowicki
quelle
Was ist mit einer regulären JPA2 @Query? Es beschwert sich über: Der Wert für das Anmerkungsattribut Query.value muss ein konstanter Ausdruck sein.
Stephane
2
Über welche @QueryAnmerkung sprichst du?
Piotr Nowicki
2
Das fully qualifiedist wichtiger, als ich dachte.
Alexander
7
Nebenbei bemerkt: Es hat nicht funktioniert, als die Aufzählung eine innere Klasse der Entität war. Wenn dies bei Ihnen nicht funktioniert, stellen Sie sicher, dass es sich bei der Aufzählung um eine eigene Datei handelt!
evandongen
-5

4 Jahre nach dem ersten Posten gibt es einige Entwicklungen. Mit Spring 4 und Hibernate 4 ist es jetzt möglich, Hibernate mit einem SpEL-Ausdruck zu "tricksen". 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 Repository-Filtermethode ü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();
    }

 }

Schließlich können wir im Repository jetzt die Filter-Klasse als einzelnen Parameter verwenden und die Abfrage veranlassen, eine Mischung aus Literalen und SpEL-Ausdrücken in ein Status-Objekt zu übersetzen:

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

Dies funktioniert einwandfrei, aber aus irgendeinem Grund habe ich es noch nicht herausgefunden. Wenn Sie das SQL-Debugging im Ruhezustand aktivieren und die Ordnerprotokollierung aktivieren, können Sie nicht sehen, dass der Ruhezustand diesen Ausdruck an Abfragevariablen bindet.

Tom Silverman
quelle
Sie sehen es nicht unter den Variablenbindungen, da die Konstante bereits in die Abfragezeichenfolge eingesetzt wurde.
AbuNassar
-6

Bitte verwenden Sie die folgende Eigenschaft in application.properties logging.level.org.hibernate.type.descriptor.sql.BasicBinder = TRACE

Santosh Choudhary
quelle