HQLとCriteriaのさまざまな組み合わせを試してみましたが、不必要な結合(両方) と不必要な選択(Criteria)を回避できませんでした。
このシナリオでは、セグメントエンティティとアプリケーションエンティティの間に@ManyToMany関係があります(ナビゲーションはセグメントからアプリケーションです)。
最初にこの基準を試しました:
Application app = ...
List<Segment> segments = session.createCriteria(Segment.class)
.createCriteria(Segment.APPLICATIONS)
.add(Restrictions.idEq(app.getId()))
.list();
次の SQL が生成されます。
select
this_.id as id1_1_,
this_.description as descript2_1_1_,
this_.name as name1_1_,
applicatio3_.segment_id as segment1_1_,
applicatio1_.id as app2_, <==== unnecessary APPLICATIONS columns
applicatio1_.id as id7_0_,
applicatio1_.name as name7_0_,
applicatio1_.accountId as accountId7_0_,
applicatio1_.applicationFlags as applicat5_7_0_,
applicatio1_.description_ as descript6_7_0_,
from
SEGMENTS this_
inner join
SEGMENTS_APPLICATIONS applicatio3_
on this_.id=applicatio3_.segment_id
inner join <==== unnecessary join
APPLICATIONS applicatio1_
on applicatio3_.app_id=applicatio1_.id
where
applicatio1_.id = ?
ご覧のとおり、Criteria は APPLICATIONS から列を選択しますが、これを選択したくありません。私はそれを行う方法を見つけていません (それは可能ですか?)。また、アプリケーション ID が既に結合テーブルSEGMENTS_APPLICATIONSにあるため、これは必要ではないと思います (HQL でも同じことが起こります)。
(追加の疑いとして、app.getId() ではなく、アプリを直接使用する制限を知りたいと思います。ご覧のとおり、クエリの HQL バージョンでそれを行うことができます)
選択部分を制限できなかったため (アプリケーション プロパティは必要ありません) 、「select」句を使用してこのHQLを試しました。
Application app = ...
List<Segment> segments = session.createQuery(
"select s from Segment s join s.applications as app where app = :app")
.setParameter("app", app)
.list();
生成するもの:
select
segment0_.id as id1_,
segment0_.description as descript2_1_,
segment0_.name as name1_,
from
SEGMENTS segment0_
inner join
SEGMENTS_APPLICATIONS applicatio1_
on segment0_.id=applicatio1_.segment_id
inner join <==== unnecessary join
APPLICATIONS applicatio2_
on applicatio1_.app_id=applicatio2_.id
where
applicatio2_.id=?
HQL が Application からプロパティを選択していないことがわかります(「select s」部分のおかげです)が、APPLICATIONSテーブルにはまだ参加していますが、これは不要だと思います。どうすればそれを避けることができますか?
(ちなみに、HQL では、基準のように app.getId() ではなく、app を直接使用できることに注意してください)
基準での「選択」と、基準と HQL の両方での不要な「結合」を回避する方法を見つけるのを手伝ってくれませんか?
(この例は @ManyToMany を使用したものですが、@OneToMany や @ManyToOne と @OneToOne でも発生すると思います。fetch = LAZY の場合でも同様です)。
どうもありがとう、フェラン