HQL 左连接条件

Cha*_*ire 5 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;
}
Run Code Online (Sandbox Code Playgroud)

类图

所以

参与-->1组

和用户 1<-->N 参与

对于给定的用户,我如何检索所有具有关联参与的组(或 null 表示没有参与)?我一直在玩连接提取,但到目前为止无济于事......

非常感谢,

中国网

附注。因此,我可以在 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;
Run Code Online (Sandbox Code Playgroud)

Adr*_*hum 7

(可能是 HQL 本身中的一些错字,但这个想法应该是正确的)

根据您的 SQL 和描述,您要问的是基于 找出所有Participation(及其对应的GroupUser,这只是

select p.id, p.group.id from Participation p where p.user.id = :userId
Run Code Online (Sandbox Code Playgroud)

为了使它更好,您应该取而代之的是获取实体:

from Participation p left join fetch p.group where p.user.id = :userId
Run Code Online (Sandbox Code Playgroud)

在理解您想要做什么时存在一些混淆:您想要所有组(无论条件如何)。而且,对于给定的用户,您希望找到该用户所涉及的所有组和参与。

虽然使用 Right-outer-join 应该是可能的:

select g, p from Participation p 
    right outer join p.group g 
    where p.user.id=:userId
Run Code Online (Sandbox Code Playgroud)

或者,在更高版本的 Hibernate (>= 5.1 ?) 中,它允许显式连接(之前没有尝试过,您可以尝试一下)(如果您使用的是 JPQL withon则替换为):

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
Run Code Online (Sandbox Code Playgroud)

或者您可以使用其他技术,例如子查询等。但是,在您的情况下,我宁愿将它们分成更简单的查询,并在您的代码中进行简单的聚合。

基本思想是有

  1. 查询所有组: from Groups
  2. 查询一个用户的所有参与情况: from Participation p join fetch p.group where p.user.id=:userId

然后您可以轻松地将它们聚合为您想要的形式,例如Map<Group, List<Participation>>,甚至更有意义的值对象。

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

  • 谢谢,除了这样我不会在没有指定用户参与的情况下获得组。 (2认同)

Dhe*_*rik -1

您需要映射实体participation中的关系GroupParticipation如果和之间的关系Group是 1..N:

class Group {
  String id
  List<Participation> participations
}
Run Code Online (Sandbox Code Playgroud)

JPQL 可以是:

SELECT g.id, p.id FROM Group g
JOIN g.participations p
JOIN p.user user
WHERE user.id = :idUser
Run Code Online (Sandbox Code Playgroud)

您可以接收此信息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
Run Code Online (Sandbox Code Playgroud)

但你不能LEFT JOIN使用这个策略。上面的查询行为就像JOIN.

在 Hibernate 中,您映射想要进行查询的关系的一侧是正常的。因此,我推荐第一种方法,映射关系。