web-dev-qa-db-ja.com

JPA基準API-JOIN句を追加する方法(可能な限り一般的な文)

クエリを動的に構築しようとしていますが、次のターゲットは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)には特定の注釈があります

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

30
Mandor

多分 Chapter 23-Using Criteria API to Using Queries of the Java EE 6チュートリアルはいくらかの光を放ちます(実際、全体を読むことをお勧めします)第23章):

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

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

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

結合メソッドは、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_などのメタモデルクラスは、永続クラスのメタ情報を記述するために使用されます。これらは通常、注釈プロセッサを使用してgenerated標準メタモデルクラス)であるか、開発者が作成できます(非標準メタモデル)。しかし、あなたの構文は奇妙に見えます。あなたが見逃した何かを模倣しようとしていると思います。

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

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

要約すると、JPA 2.0基準とメタモデルAPIについてもう少し読む必要があると思います。開始点として、以下のリソースを暖かくお勧めします。

こちらもご覧ください

関連する質問

40
Pascal Thivent

実際に、アノテーションが正しい場合は、静的メタモデルを扱う必要はありません。

次のエンティティ:

@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));
14

JPAを学ぶ必要はありません。 JPA2の簡単な基準を使用できます( 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);

OR

List<Tuple> result =  CriteriaProcessor.findAllTuple(petCriteria);
5
user793442

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

この投稿とSun Java EE 6 JPA 2の例は、JPA 2の理解を実際に妨げました。この投稿に戻ると、その後も混乱しました。

5
Chris Harris