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回、where述語用に1回。結果の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を使用する方が良いようです。
root.join(...)
の代わりに、root.fetch(...)
を使用して_Fetch<>
_オブジェクトを返すことができます。
_ ただし、同様の方法で使用できます。Fetch<>
_は_Join<>
_の子孫です
_Fetch<>
_を_Join<>
_にキャストするだけで、EclipseLinkおよびHibernateで動作するはずです。
_...
Join<MyEntity, RelatedEntity> join = (Join<MyEntity, RelatedEntity>)root.fetch("relatedEntity");
...
_
JPA 2.1以降では、動的なエンティティグラフを使用できます。フェッチを削除し、次のようにエンティティグラフを指定します。
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");
query.select(root).where(builder.equal(join.get("id"), 3));
EntityGraph<MyEntity> fetchGraph = entityManager.createEntityGraph(MyEntity.class);
fetchGraph.addSubgraph("relatedEntity");
entityManager.createQuery(query).setHint("javax.persistence.loadgraph", fetchGraph);
EclipseLinkでroot.fetch()
を使用すると、3つのタイプがあり、デフォルトはINNERであるため、INNER JOIN
でSQLが作成されます。
INNER, LEFT, RIGHT;
提案は、CreateQueryを使用することです。
TypedQuery<T> typedQuery = entityManager.createQuery(query);
編集:次のようにルートをキャストすることができます:
From<?, ?> join = (From<?, ?>) root.fetch("relatedEntity");