2016-09-29 4 views
2

Это может показаться основным, но уже поздно, и у меня возникают проблемы со следующим.HQL left join with condition

class Group { 

    @Id 
    String id; 
} 

class Participation { 

    @Id 
    String id; 

    @ManyToOne 
    @JoinColumn(name = "GROUP_ID") 
    Group group; 

    @ManyToOne 
    @JoinColumn(name = "USER_ID") 
    User user; 
} 

class User { 

    @Id 
    String id; 

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
    Set<Participation> participations; 
} 

Class diagram

Так

Участие -> 1 группа

пользователя и 1 < -> N Участие

Как я могу получить все группы с, для данный Пользователь, связанное с ним участие (или null - нет)? Я играл с присоединиться получений фидов, но безрезультатно до сих пор ...

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

CN

PS. Я могу это сделать в SQL таким образом:

select g.d, p.id 
from group as g 
left join participation as p 
on p.group_id = g.id and p.user_id = 2; 
+0

Редактировать: Добавлено диаграмму и лучшее решение sql ... – ChambreNoire

ответ

-1

Вы должны сопоставить participation отношения в Group сущности. Если отношения между Participation и Group является 1..N:

class Group { 
    String id 
    List<Participation> participations 
} 

JPQL может быть:

SELECT g.id, p.id FROM Group g 
JOIN g.participations p 
JOIN p.user user 
WHERE user.id = :idUser 

Вы можете получить эту информацию в качестве List<Object[]> (Object[0] является идентификатор группы и Object[1] является участие идентификатор) или используйте SELECT NEW.

Без карты/Участие отношения группы, вы можете сделать:

SELECT g.id, p.id FROM Group g, Participation p 
JOIN p.user user 
JOIN p.group groupp 
WHERE g.id = groupp.id 
AND user.id = :idUser 

Но вы не можете сделать LEFT JOIN, используя эту стратегию. Запрос выше типов поведения, таких как JOIN.

Это нормально с Hibernate, вы сопоставляете сторону отношений, которые вы хотели бы сделать. Поэтому я рекомендую первый подход, сопоставляющий отношения.

+0

Я боюсь, что отношения между участием и группой не 1: 1 (я добавил диаграмму к исходному вопросу). – ChambreNoire

+0

@ChambreNoire, без проблем! Я отредактировал мой вопрос, но работает точно так же – Dherik

+0

Без возможности сделать это без добавления группы> Ассоциация участия? – ChambreNoire

3

(Вероятно, некоторые опечатка в самом HQL, но идея должна быть правильной)

То, что вы просите, основываясь на вашем SQL и описания, это выяснить, все Participation (и его соответствующие Group) на основе User, который просто

select p.id, p.group.id from Participation p where p.user.id = :userId 

Чтобы сделать это лучше, вы должны принести сущности вместо:

from Participation p left join fetch p.group where p.user.id = :userId 

Были некоторые недоумения в понимании того, что вы пытались сделать: Вы хотите, чтобы все группы (независимо от состояния). И для данного пользователя вы хотите найти все группы и участие, которые задействованы пользователем.

Хотя это должно быть возможно с помощью правой внешнее_соединение:

select g, p from Participation p 
    right outer join p.group g 
    where p.user.id=:userId 

Или, в более поздней версии Hibernate (?> = 5,1), что позволяет Явные (не пробовал раньше, вы можете дать ему попробовать) (Заменить with с on, если вы используете JPQL):

select g, p from Group g 
    left outer join Participation p 
     with p.group = g 
    left outer join p.user u 
    where u.id = :userId 

Или вы можете использовать другие методы, такие как подзапросы и т.д. Однако я предпочел бы разделить их на более простые запросы в вашем случае и сделать простая агрегация в вашем коде.

Основная идея состоит в том, чтобы иметь

  1. запроса для всех групп: from Groups
  2. Query для всех участий для пользователя: from Participation p join fetch p.group where p.user.id=:userId

Затем вы можете объединить их легко с вами форме хотите, например Map<Group, List<Participation>>, или даже более значимый объект ценности.

Преимущество в том, что запрос доступа к данным более простой и многоразовый (esp, если вы их обертываете в метод поиска DAO/Repository). Еще одна поездка в DB не должна вызывать очевидного влияния на производительность.

+1

Спасибо, за исключением того, что таким образом я не получаю Группы без участия для указанного Пользователя. – ChambreNoire

+0

У меня нет dbms под рукой, но вы делаете левое соединение, так как ваш пример с идентификатором пользователя должен все же давать вам только группу с участником, не так ли? И вы попросили «для данного пользователя, данное участие», которое дает вам участие без пользователя, противоречит тому, что вы просили. Во всяком случае, попробуйте «от участия p left join p.user u, где u.id =: userid или u is null» –

+0

Аг, я думаю, я неправильно понял, что вы просили. Вы действительно хотите, чтобы все группы были правы? Во всяком случае, iirc, HQL действительно поддерживают Right Join, поэтому вы можете начать с права участия join p.group? –