带有数组聚合的 CriteriaQuery

问题描述 投票:0回答:1

我想对自定义数据访问类执行查询。不幸的是我被困在中途了。

class User {
  private Long id
  private String name
  private Set<Group> groups
...
}

class Group {
  private Long id
  private String name
...
}

我想构造与以下 sql 语句等效的内容

select user.id, user.name, ARRAY_AGG(user_groups.groups_id) from user left join user_groups ON user_groups.user_id = user.id group by user.id

我尝试了以下方法

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery query = criteriaBuilder.createQuery(CustomUser.class)
Root<ENTITY> entryRoot = query.from(User.class);
query.groupBy(entryRoot.get("ident");

如果我使用连接进行多选,则会失败,因为缺少聚合函数

query.multiselect(entryRoot.get("id"), entryRoot.get("name"), entryRoot.join("groups", JoinType.Left)

我尝试将数组聚合添加到多选中

arraySelection = CompoundSelection<Object[]> array = criteriaBuilder.array(entryRoot.join("groups", JoinType.LEFT));
query.multiselect(entryRoot.get("id"), entryRoot.get("name"), arraySelection)

不幸的是,这失败了,因为复合选择不允许与多选中的其他选择一起使用。

如何使用 CriteriaQuery 执行数组聚合?

我知道,我可以简单地使用

CriteriaQuery query = criteriaBuilder.createQuery(User.class)

而不是

CriteriaQuery query = criteriaBuilder.createQuery(CustomUser.class)

但我想添加仅反向相关实体的进一步连接。实际上我陷入了重建自动完成的事情,稍后添加更多功能。

java hibernate jpa criteria hibernate-criteria
1个回答
0
投票

要使用 Postgres 中可用的数组聚合,请使用具有定义的 array_agg 函数的扩展 Postgres-Dialect。

public class ExtendedPostgreSQL9Dialect extends PostgreSQL9Dialect {

    public ExtendedPostgreSQL9Dialect() {
        super();
        registerFunction("array_agg", new StandardSQLFunction("array_agg", StandardBasicTypes.STRING));
    }
}

必须在配置 yml 或代码中配置方言

jpa.hibernate.dialect:ExtendedPostgreSQL9Dialect

这样就可以构造逆连接的子查询了

        Subquery<String> subquery = query.subquery(String.class);
        Root<> subFrom = subquery.from(parentClass);
        Join<Object, Object> join = subFrom.join(fieldName);
        join.on(criteriaBuilder.equal(entryRoot.get("id"), join.get("id")));
        Expression<String> function = criteriaBuilder.function("array_agg", String.class, join.getParent()
                                                                                              .get("id"));
        subquery.select(function);

在查询本身中,必须添加子查询的选择

query.multiselect(..., subquery.getSelection());
© www.soinside.com 2019 - 2024. All rights reserved.