次のエンティティがあります: イベントと属性。イベントは多くの属性を持つことができます。
私が抱えている問題は、イベントとその属性を単一の SQL クエリで返すクエリが見つからないように見えることです。何百万ものイベントを反復処理する必要があり、明らかなパフォーマンス上の理由から、それらすべてを遅延ロードしたくありません。
クエリで fetch を使用してみましたが、属性ごとにイベントが返されます。つまり、イベントに 2 つの属性がある場合、それぞれ 1 つの属性を持つ 2 つのイベントが返されます。
私が欲しいのは、2 つの属性を持つ 1 つのイベントです。
SELECT e FROM Event e LEFT JOIN FETCH e.attributes
DISTINCT を追加すると機能しますが、大規模なデータ セットでは非常に遅い個別の SQL クエリが作成されます。
public class Event {
@OneToMany(mappedBy = "event", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
public Set<Attribute> getAttributes(){}
}
public class Attribute {
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name = "event_id", nullable = false)
public Event getEvent() {
return event;
}
}
解決
JPA ソリューションが見つかりませんでした。代わりに、EntityManager を Hibernate セッションにラップ解除し、@milkplusvellocet が提案したように基準の結果トランスフォーマーを使用しました。これにより、別個の SQL クエリを作成せずに、別個のルート エンティティが取得されます。
Session session = em.unwrap(Session.class);
Criteria criteria = session.createCriteria(Event.class);
criteria.setFetchMode("attributes", FetchMode.JOIN);
criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
注意すべきことの 1 つは、ラップされていないセッションから HQL を使用してみたことです。クエリに DISTINCT を追加し、上記の条件ソリューションと同様に、結果トランスフォーマーを DISTINCT_ROOT_ENTITY に設定しました。このようにしても、別個の SQL クエリが作成されます。