java Hibernate为@ManyToMany关系中的每个延迟加载元素创建SELECT查询

yr9zkbsy  于 2023-03-16  发布在  Java
关注(0)|答案(1)|浏览(137)

我正在处理一个有50k条目的PostgreSQL表USERS。一个USER可以有一个或多个GROUP。这两个表使用连接表USER_GROUP(带有user_id和group_id)连接。关系定义为:

@ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name="user_group",
            joinColumns={
                    @JoinColumn(name="user_uid", referencedColumnName="user_uid")},
            inverseJoinColumns={
                    @JoinColumn(name="group_id", referencedColumnName="group_id")})
    private Set<GroupEntity> groups = new HashSet<>();

在真实的的数据库中,很少有用户有一个指定的组。在一个用例中,我需要查询所有用户和他们各自的组。组名需要存储在一个字符串中。我使用以下命令加载组:

String groups = userList.add(String.join(",", user.getGroups().stream().map(Group::getName)                                                                  .collect(Collectors.toList())));

这个查询非常慢,因为Hibernate会为每个用户创建一个选择查询。有什么方法可以加快速度吗?我错过了什么吗?
我的替代方法是创建一个数据库视图:

CREATE VIEW user_view AS SELECT user.user_id, group_names from user left outer join (select user_id, string_agg(group_name, ',') group_names from user_group natural left join group GROUP BY user_id) AS g ON user.user_id = g.user_id;

有没有一种方法可以有效地使用Hibernate来完成这个任务?我使用的是Quarkus和Panache,但是也有一些Criteria代码。
我希望我的例子容易理解:)

0yg35tkg

0yg35tkg1#

是的,实际上非常简单。你可以在你的HQL查询中使用连接获取:

select u from UserEntity u join fetch u.groups

通过这种方式,Hibernate将沿着所有集合元素作为单个查询的一部分进行连接和获取。其他可能的替代方法是使用实体图,或专门的HQL查询,例如。

select u.id, string_agg(g.name, ",") from UserEntity u join u.groups g group by u.id

最后一个查询将选择用户id和逗号分隔的列表作为字符串。

相关问题