我想对自定义数据访问类执行查询。不幸的是我被困在中途了。
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)
但我想添加仅反向相关实体的进一步连接。实际上我陷入了重建自动完成的事情,稍后添加更多功能。
要使用 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());