Как избежать ненужных операций выбора и объединения в HQL и Criteria

Я пробовал разные комбинации HQLи Criteria, и мне не удалось избежать некоторых ненужных joins(в обоих) и некоторые ненужные selects(в Criteria).

В нашем сценарии у нас есть отношение @ManyToManyмежду сущностями Segmentи Application(навигация осуществляется от сегмента к приложениям).

Сначала я попробовал это Criteria:

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, которые я не хочу быть выбранным. Я не нашел способ сделать это (возможно ли это?). Кроме того, он соединяется с APPLICATIONS, что, я думаю, не нужно, потому что идентификатор приложения уже находится в таблице соединения SEGMENTS_APPLICATIONS (то же самое происходит с HQL).

(В качестве дополнительного сомнения, я хотел бы знать Ограничение, которое использует приложение напрямую, а не app.getId().Как вы увидите, я мог сделать это в HQL-версии запроса)

Поскольку я не мог ограничить часть выбора (мне не нужны свойства приложения), я попробовал этот HQLс Предложение «select»:

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 напрямую, а не app.getId(), как в Criteria)

Не могли бы вы помочь мне найти способ избежать «выборов» в Criteria и ненужные «соединения» как в Criteria, так и в HQL?

(Это пример с @ManyToMany, но я думаю, что это также происходит с @OneToMany, а также с @ManyToOne и @OneToOne, даже с fetch = LAZY).

Большое спасибо, Ferran

6
задан Ferran Maylinch 19 May 2012 в 13:04
поделиться