7

HQLCriteriaのさまざまな組み合わせを試してみましたが、不必要な結合(両方) と不必要な選択(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 の場合でも同様です)。

どうもありがとう、フェラン

4

1 に答える 1

6

Criteria を使用するときに選択される追加の列は、 Hibernate の長年にわたるバグに由来します。私の知る限り、それを回避する唯一の方法は、HQL または JPA2 基準 API を使用することです。

他の問題もバグとして通知されますが、影響は少なく、あまり気にしません。

于 2012-05-19T12:34:55.607 に答える