jpa 使用数组聚合的CriteriaQuery

yrdbyhpb  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(93)

我想对一个自定义的数据访问类执行查询。不幸的是,我被卡住了。

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)


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

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)


但我想添加更多的连接,只有反向相关的实体。实际上,我被困在重建的东西自动完成,做添加更多的功能后。

am46iovg

am46iovg1#

要使用Postgres中可用的Array-Aggregation,请使用定义了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());

相关问题