5

ORDER BYJPA CriteriaBuilderを使用してクエリを作成し、句を追加したいと思います。これは私の実体です:

@Entity
@Table(name = "brands")
public class Brand implements Serializable {

    public enum OwnModeType {
        OWNER, LICENCED
    }

    @EmbeddedId
    private IdBrand id;
    private String code;
    //bunch of other properties
}

埋め込みクラスは次のとおりです。

@Embeddable
public class IdBrand implements Serializable {

    @ManyToOne
    private Edition edition;
    private String name;
}

そして、クエリを作成する方法は次のようになります。

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Brand> q = cb.createQuery(Brand.class).distinct(true);
Root<Brand> root = q.from(Brand.class);
if (f != null) {
    f.addCriteria(cb, q, root);
    f.addOrder(cb, q, root, sortCol, ascending);
}
return em.createQuery(q).getResultList();

そしてここに呼ばれる関数があります:

public void addCriteria(CriteriaBuilder cb, CriteriaQuery<?> q, Root<Brand> r) {
}

public void addOrder(CriteriaBuilder cb, CriteriaQuery<?> q, Root<Brand> r, String sortCol, boolean ascending) {
    if (ascending) {
        q.orderBy(cb.asc(r.get(sortCol)));
    } else {
        q.orderBy(cb.desc(r.get(sortCol)));
    }
}

sortCol次のような設定をしようとすると"id.name"、次のエラーが発生します。

javax.ejb.EJBException:java.lang.IllegalArgumentException:パスに対して属性[id.name]を解決できません

どうすればそれを達成できるでしょうか?ORDER BYオンラインで検索してみましたが、ヒントが見つかりませんでした...関係があるときに同様のことができれば素晴らしいと思い@ManyToOneます(たとえば"id.edition.number"

4

2 に答える 2

6

問題は、JPA パスの使用法を理解していることです。JPAマニュアルは次のように述べています。

タイプが永続化可能なユーザー クラスであるパス式は、ドット (.) 演算子を再利用してさらに拡張できます。たとえば、c.capital.name は、Capital エンティティ オブジェクトからその名前フィールドまで続くネストされたパス式です。パス式をさらに拡張できるのは、そのタイプがユーザー定義の持続可能クラスでもある場合のみです。ドット (.) 演算子は、コレクション、マップ、および単純型 (数値、ブール値、文字列、日付) の値には適用できません。

あなたの場合、id.edition.number を使用しました。ここで、IdBrand (id) はユーザーが永続化できるクラスではありません。

解決するには、次の方法でパス式を作成します。root.get("id").get("edition.number");


javax.persistence.metamodel.Attribute.PersistentAttributeTypeこのような問題を回避するために、パスの構築方法を決定するパス ビルダーを作成できます。基本要素には .get() を使用し、コレクション要素には .join() を使用します。

エラーを理解するには、一般的な JPA パスに関する詳細情報を読む必要があります。これは、JPA パスに関する優れたマニュアルです。

于 2012-04-16T13:39:39.880 に答える
1

私は実際に別の同様の問題に関する答えを見つけました:JPA-CriteriaAPIとEmbeddedId

コードを修正した方法は次のとおりです。

public void addOrder(CriteriaBuilder cb, CriteriaQuery<?> q, Root<Brand> r, String sortCol, boolean ascending) {
    Path<?> p = r;
    String []sortCols = sortCol.split("\\."); // This is a regexp, hence the escape backslash
    for(String sc: sortCols) {
        p = p.get(sc);
    }
    if (ascending) {
        q.orderBy(cb.asc(p));
    } else {
        q.orderBy(cb.desc(p));
    }
}
于 2012-04-15T11:26:47.370 に答える