You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决HQL排序时org.hibernate.QueryException集合解引用非法问题

解决方案:按关联集合首个元素的属性排序A对象

问题背景

需要查询所有A类型对象,并按照a.getListB().get(0).getC().getLastname()排序(listB按id升序排列,取第一个元素关联C的lastname)。原HQL因直接引用集合报错,原生SQL结果不符合预期。


HQL 实现方案

通过子查询获取每个A关联的最小id的B(对应listB.get(0),因为listB按id排序),再取其关联C的lastname作为排序依据:

SELECT a FROM A a 
ORDER BY (
    SELECT c.lastname 
    FROM B b 
    WHERE b.a = a 
    ORDER BY b.id ASC 
    LIMIT 1
) ASC

Criteria API 实现方案

用Criteria构建子查询,筛选每个A对应的首个B的C的lastname:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<A> query = cb.createQuery(A.class);
Root<A> root = query.from(A.class);

// 子查询获取每个A对应的第一个B的C的lastname
Subquery<String> subquery = query.subquery(String.class);
Root<B> bRoot = subquery.from(B.class);
Join<B, C> cJoin = bRoot.join("c");
subquery.select(cJoin.get("lastname"))
        .where(cb.equal(bRoot.get("a"), root))
        .orderBy(cb.asc(bRoot.get("id")))
        .setMaxResults(1);

query.select(root)
     .orderBy(cb.asc(subquery));

List<A> result = entityManager.createQuery(query).getResultList();

原生SQL 实现方案

修正原生SQL逻辑,先预查询每个A对应的首个B的C的lastname,再关联排序:

SELECT a.* 
FROM A a
LEFT JOIN (
    SELECT b.a_id, c.lastname 
    FROM B b
    JOIN C c ON b.uploaded_from = c.id
    WHERE b.id = (
        SELECT MIN(b2.id) FROM B b2 WHERE b2.a_id = b.a_id
    )
) b_first ON a.id = b_first.a_id
ORDER BY b_first.lastname ASC;

内容的提问来源于stack exchange,提问作者javaistaucheineinsel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 09:01:03