46

クエリを動的に構築しようとしていますが、次のターゲットは JOIN 句を追加することです (API の使用方法がわかりません)。

たとえば、今では、このコードは私のために機能します:

...
Class baseClass;   
...
CriteriaBuilder cb = JpaHandle.get().getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery(this.baseClass);
Root entity_ = cq.from(this.baseClass); 
Predicate restrictions = null;
...
restrictions = cb.conjunction();
restrictions = cb.and(restrictions, entity_.get("id").in(this.listId));
...
cq.where(restrictions);
...
Query qry = JpaHandle.get().createQuery(cq);

(注: JpaHandle は wicket-JPA 実装からのものです)

私の望みは JOIN 句を追加することです (できるだけ一般的に)!

クラス(this.baseClass)に特定の注釈があります

例えば ​​:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "assay_id", nullable = false)

それで、標準のJPAでこのような方法はありますか?(注:これはコンパイルされません)

ここで実用的な失敗が近づいています:

...
Join<Experiment,Assay> experimentAssays = entity_.join( entity_.get("assay_id") );

またはそのように:

...
CriteriaQuery<Customer> q = cb.createQuery(Customer.class);
Root<Customer> c = q.from(Customer.class);
SetJoin<Customer, PurchaseOrder> o = c.join(Customer_.orders);

私にとって、それが可能な限り一般的であることができれば、それは素晴らしいことです...:

...
Join joinClause = entity_join(entity_.get("assay_id"), entity2_.get("id"));

もちろん、クラス (this.baseClass) には特定の注釈があります。

お時間をいただきありがとうございます。私はあらゆる種類のコメントに感謝します!

4

4 に答える 4

61

たぶん、第23章からの次の抜粋-CriteriaAPIを使用して JavaEE 6チュートリアルのクエリを作成すると、多少の光が当たるでしょう(実際には、第23章全体を読むことをお勧めします)。

結合を使用した関係のクエリ

関連するエンティティクラスに移動するクエリの場合、クエリはFrom.join、クエリルートオブジェクトまたは別の joinオブジェクトのメソッドの1つを呼び出して、関連するエンティティへの結合を定義する必要があります。結合メソッドはJOIN、JPQLのキーワードに似ています。

結合のターゲットは、タイプのMetamodelクラスを使用して、結合 EntityType<T>されたエンティティの永続フィールドまたはプロパティを指定します。

結合メソッドは、タイプがオブジェクトを返しますJoin<X, Y>。ここXで、はソースエンティティでありY、は結合のターゲットです。

例23-10クエリへの参加

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Metamodel m = em.getMetamodel();
EntityType<Pet> Pet_ = m.entity(Pet.class);

Root<Pet> pet = cq.from(Pet.class);
Join<Pet, Owner> owner = pet.join(Pet_.owners);

結合をチェーン化して、Join<X, Y>結合ごとにインスタンスを作成しなくても、ターゲットエンティティの関連エンティティに移動できます。

例23-11クエリで結合を連鎖させる

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Metamodel m = em.getMetamodel();
EntityType<Pet> Pet_ = m.entity(Pet.class);
EntityType<Owner> Owner_ = m.entity(Owner.class);

Root<Pet> pet = cq.from(Pet.class);
Join<Owner, Address> address = cq.join(Pet_.owners).join(Owner_.addresses);

そうは言っても、私はいくつかの追加の意見があります:

まず、コードの次の行:

Root entity_ = cq.from(this.baseClass);

どういうわけか静的メタモデルクラスの部分を見逃したと思います。Pet_引用された例のようなメタモデルクラスは、永続クラスのメタ情報を記述するために使用されます。これらは通常、アノテーションプロセッサ(正規のメタモデルクラス)を使用して生成されるか、開発者が作成できます(非正規のメタモデル)。しかし、あなたの構文は奇妙に見えます、私はあなたがあなたが逃した何かを模倣しようとしていると思います。

第二に、私はあなたがこの外部キーを忘れるべきだと本当に思いますassay_id、あなたはここで間違った道を進んでいます。テーブルや列ではなく、オブジェクトと関連付けについて考え始める必要があります。

第三に、 JOIN句を可能な限り一般的に追加することで何を意味するのか、オブジェクトモデルがどのように見えるのかを正確に理解することはできません(前のポイントを参照)。したがって、あなたの質問にもっと正確に答えることは不可能です。

要約すると、JPA 2.0CriteriaとMetamodelAPIについてもう少し読む必要があると思います。出発点として、以下のリソースを温かくお勧めします。

も参照してください

関連する質問

于 2010-08-06T20:43:54.197 に答える
23

実際、注釈が正しければ、静的メタモデルを扱う必要はありません。

次のエンティティを使用:

@Entity
public class Pet {
  @Id
  protected Long id;
  protected String name;
  protected String color;
  @ManyToOne
  protected Set<Owner> owners;
}

@Entity
public class Owner {
  @Id
  protected Long id;
  protected String name;
}

これを使用できます:

CriteriaQuery<Pet> cq = cb.createQuery(Pet.class);
Metamodel m = em.getMetamodel();
EntityType<Pet> petMetaModel = m.entity(Pet.class);

Root<Pet> pet = cq.from(Pet.class);
Join<Pet, Owner> owner = pet.join(petMetaModel.getSet("owners", Owner.class));
于 2012-12-13T09:41:29.637 に答える
6

警告!Sun JPA 2 の例には多くのエラーがあり、その結果、パスカルの回答に貼り付けられたコンテンツが表示されます。この投稿を参照してください。

この投稿と Sun Java EE 6 JPA 2 の例は、私の JPA 2 の理解を妨げてしまいました。 .

于 2013-02-07T01:23:50.827 に答える
4

JPAを学ぶ必要はありません。JPA2 の easy-criteria ( https://sourceforge.net/projects/easy-criteria/files/ ) を使用できます。これが例です

CriteriaComposer<Pet> petCriteria CriteriaComposer.from(Pet.class).
where(Pet_.type, EQUAL, "Cat").join(Pet_.owner).where(Ower_.name,EQUAL, "foo");

List<Pet> result = CriteriaProcessor.findAllEntiry(petCriteria);

また

List<Tuple> result =  CriteriaProcessor.findAllTuple(petCriteria);
于 2011-06-10T21:55:25.350 に答える