Problemy z wykonywaniem zapytania podczas korzystania z Enum w encji


86

Mam następujące elementy w encji Pytanie:

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

i

@Enumerated(EnumType.STRING)
private Status status;

// usual accessors

Otrzymuję ten wyjątek:

Opis wyjątku: Błąd podczas kompilowania kwerendy [Question.countApproved: SELECT COUNT(q) FROM Question q WHERE q.status = 'APPROVED'], wiersz 1, kolumna 47: nieprawidłowe wyliczenie równe, nie można porównać wartości wyliczenia typu [myCompnay.application.Status]z wartością typu innego niż wyliczenie [java.lang.String]. w org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy (EntityManagerSetupImpl.java:501)

Jak to naprawić?


czy używasz niestandardowego wyliczenia? Czy możesz zaktualizować dokument, aby wyświetlić wyliczenie statusu?
Gonzalo Garcia Lasurtegui

Odpowiedzi:


159

Myślę, że powinieneś użyć swojego (w pełni kwalifikowanego) Statuswyliczenia zamiast wartości dosłownej, więc coś takiego: (zakładając, że twoje Statuswyliczenie jest w com.myexamplepakiecie)

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

A co ze zwykłym JPA2 @Query? Narzeka: Wartość atrybutu adnotacji Query.value musi być wyrażeniem stałym.
Stephane,

2
O @Queryjakiej adnotacji mówisz?
Piotr Nowicki

2
To fully qualifiedjest ważniejsze niż myślałem, że może być.
aleksander

9
Na marginesie: nie działało, gdy wyliczenie było wewnętrzną klasą jednostki. Jeśli to nie zadziała, upewnij się, że wyliczenie jest własnym plikiem!
evandongen

@evandongen jakieś rozwiązanie, jeśli wyliczenie jest klasą wewnętrzną?
Raja aar

-5

Po 4 latach od pierwszego stanowiska nastąpiły pewne zmiany. Używając spring 4 i Hibernate 4, można teraz „oszukać” Hibernate, używając wyrażenia SpEL. Na przykład:

Wyliczenie:

package com.mycompany.enums

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

Oto klasa opakowania o nazwie „Filter”, którą przekażemy do metody filtrowania repozytorium.

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

 }

Wreszcie w repozytorium możemy teraz użyć klasy Filter jako pojedynczego parametru i sprawić, że zapytanie przetłumaczy coś, co wydaje się być mieszaniną literałów i wyrażeń SpEL na obiekt Status:

Repozytorium:

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

Działa to doskonale, ale z jakiegoś dziwnego powodu, którego jeszcze nie rozgryzłem, jeśli włączysz debugowanie SQL w hibernacji i włączysz rejestrowanie spinacza, nie będziesz w stanie zobaczyć Hibernacji wiążącej to wyrażenie ze zmiennymi zapytania.


Nie widać tego wśród powiązań zmiennych, ponieważ stała została już podstawiona do ciągu zapytania.
AbuNassar,

-6

Użyj poniższej właściwości w application.properties logging.level.org.hibernate.type.descriptor.sql.BasicBinder = TRACE

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.