解决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
相关产品推荐
相关产品推荐

