32

JPA 2.0 を使用します。デフォルト (明示的なフェッチなし) では、@OneToOne(fetch = FetchType.EAGER)フィールドは 1 + N 個のクエリでフェッチされるようです。N は、個別の関連エンティティとの関係を定義するエンティティを含む結果の数です。Criteria API を使用して、次のようにそれを回避しようとするかもしれません。

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<MyEntity> query = builder.createQuery(MyEntity.class);
Root<MyEntity> root = query.from(MyEntity.class);
Join<MyEntity, RelatedEntity> join = root.join("relatedEntity");
root.fetch("relatedEntity");
query.select(root).where(builder.equals(join.get("id"), 3));

上記は、理想的には次と同等である必要があります。

SELECT m FROM MyEntity m JOIN FETCH myEntity.relatedEntity r WHERE r.id = 3

ただし、条件クエリにより、ルート テーブルが関連するエンティティ テーブルに不必要に 2 回結合されます。1 回はフェッチ用、もう 1 回は where 述語用です。結果の SQL は次のようになります。

SELECT myentity.id, myentity.attribute, relatedentity2.id, relatedentity2.attribute 
FROM my_entity myentity 
INNER JOIN related_entity relatedentity1 ON myentity.related_id = relatedentity1.id 
INNER JOIN related_entity relatedentity2 ON myentity.related_id = relatedentity2.id 
WHERE relatedentity1.id = 3

残念ながら、フェッチだけを行うと、where 句で使用する式がありません。

何か不足していますか、それとも Criteria API の制限ですか? 後者の場合、これは JPA 2.1 で修正されていますか、それともベンダー固有の拡張機能はありますか?

それ以外の場合は、コンパイル時の型チェックをあきらめて (私の例ではメタモデルを使用していないことに気付きました)、動的な JPQL TypedQueries を使用する方がよいようです。

4

3 に答える 3

38

代わりに、which を返すオブジェクトroot.join(...)を使用できます。root.fetch(...)Fetch<>

Fetch<>の子孫ですJoin<>しかし、同様の方法で使用できます。

EclipseLinkとHibernateで動作するようにキャストFetch<>するだけですJoin<>

...
Join<MyEntity, RelatedEntity> join = (Join<MyEntity, RelatedEntity>)root.fetch("relatedEntity");
...
于 2013-06-25T20:48:41.387 に答える
1

root.fetch()EclipseLink で使用すると、SQL が作成されますINNER JOIN。これは、3 つの型があり、デフォルトが INNER であるためです。

INNER,  LEFT,  RIGHT;

提案は、CreateQuery を使用することです。

TypedQuery<T> typedQuery = entityManager.createQuery(query);

編集:次のようにルートをFromにキャストできます:

From<?, ?> join = (From<?, ?>) root.fetch("relatedEntity");
于 2015-04-27T13:50:05.543 に答える