HQL离开了条件的连接

时间:2016-09-29 19:53:41

标签: java sql hibernate join hql

这看起来很基本,但已经很晚了,我遇到了以下问题。

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

所以

参与 - &gt; 1组

和用户1&lt; - &gt; 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;

2 个答案:

答案 0 :(得分: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

在理解你想要做的事情时有一些困惑: 你想要所有的团体(无论条件如何)。而且,对于给定的用户,您希望查找用户参与的所有组和参与。

虽然应该可以使用Right-outer-join:

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

或者,在更高版本的Hibernate(&gt; = 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. 查询用户的所有参与:from Participation p join fetch p.group where p.user.id=:userId
  3. 然后,您可以轻松地将它们聚合到您想要的表单,例如Map<Group, List<Participation>>,或者更有意义的价值对象。

    好处是数据访问查询更简单,更可重用(特别是如果您将它们包装在DAO / Repository finder方法中)。再往返一次DB不应该在这里产生任何明显的性能影响。

答案 1 :(得分:-1)

您需要在participation实体中映射Group关系。如果ParticipationGroup之间的关系为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]是群组ID,Object[1]是参与ID)或使用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,您可以映射您想要进行查询的关系的一侧。所以,我推荐第一种方法,即映射关系。