Я пробовал разные комбинации HQL и критериев, и мне не удалось избежать ненужных объединений (в обоих) и некоторых ненужных выбирает (в критериях).
В нашем сценарии у нас есть связь @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, которые я не хочу выбирать. Я не нашел способа сделать это (возможно ли это?). Кроме того, он соединяется с ПРИЛОЖЕНИЯМИ, что, на мой взгляд, необязательно, поскольку идентификатор приложения уже находится в таблице соединения 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 не выбирает свойства из приложения (благодаря части "select s"), но по-прежнему присоединяется к таблице APPLICATIONS, что я считаю ненужным. Как этого избежать?
(В качестве примечания обратите внимание, что в HQL я мог использовать приложение напрямую, а не app.getId (), как в критериях)
Не могли бы вы помочь мне найти способ избежать «выборок» в критериях и ненужных «объединений» как в критериях, так и в HQL?
(Этот пример с @ManyToMany, но я думаю, что это также происходит с @OneToMany, а также с @ManyToOne и @OneToOne, даже с fetch = LAZY).
Большое спасибо, Ферран