エンティティでEnumを使用する場合のクエリの作成に関する問題


83

質問エンティティに次のものがあります。

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

そして

@Enumerated(EnumType.STRING)
private Status status;

// usual accessors

この例外が発生します:

例外の説明:クエリのコンパイル中にエラーが発生しました[Question.countApproved:SELECT COUNT(q) FROM Question q WHERE q.status = 'APPROVED']、行1、列47:無効な列挙型の等しい[myCompnay.application.Status][java.lang.String]。タイプの列挙型の値をタイプの非列挙型の値と比較できません 。org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:501)で

これを修正するにはどうすればよいですか?


カスタム列挙型を使用していますか?ドキュメントを更新してステータス列挙型を表示できますか?
ゴンザロガルシアラスルテギ2011年

回答:


154

Statusリテラル値の代わりに(完全に修飾された)列挙型を使用する必要があると思うので、次のようになります:(Status列挙型がcom.myexampleパッケージに含まれていると仮定)

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

JPA2の通常の@Queryはどうですか?注釈属性Query.valueの値は定数式でなければなりません。
ステファン

2
どんな@Query注釈について話しているのですか?
Piotr Nowicki 2014

2
これfully qualifiedは私が思っていたようにもっと重要です。
アレクサンダー2015

6
補足:列挙型がエンティティの内部クラスである場合は機能しませんでした。これがうまくいかない場合は、列挙型が独自のファイルであることを確認してください。
evandongen

-5

最初のポストから4年、いくつかの進展があります。Spring4とHibernate4を使用すると、SpEL式を使用してHibernateを「トリック」できるようになりました。例えば:

列挙型:

package com.mycompany.enums

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

これが「Filter」というラッパークラスで、リポジトリのフィルタリングメソッドに渡します。

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

 }

最後に、リポジトリで、Filterクラスを単一のパラメーターとして使用し、クエリでリテラルとSpEL式の混合のように見えるものをStatusオブジェクトに変換できるようになりました。

レポジトリ:

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

これは完全に機能しますが、私がまだ理解していない奇妙な理由で、HibernateでSQLデバッグを有効にし、バインダーロギングをオンにすると、Hibernateがこの式をクエリ変数にバインドするのを見ることができなくなります。


定数はすでにクエリ文字列に代入されているため、変数バインディングには表示されません。
AbuNassar 2018

-6

application.propertiesの以下のプロパティlogging.level.org.hibernate.type.descriptor.sql.BasicBinder = TRACEを使用してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.