Hibernate Criteria如何实现含max()函数的多列子查询
将指定SQL转换为Hibernate Criteria查询
原SQL逻辑
原SQL通过子查询获取每个ueb_uuid对应的最大version,再关联主表筛选出每个ueb_uuid的最新版本数据:
SELECT a.* FROM objekt a, -- Filter on max version ( SELECT ueb_uuid, MAX(version) AS version FROM objekt GROUP BY ueb_uuid ) b WHERE a.version = b.version AND a.ueb_uuid = b.ueb_uuid;
问题分析
核心难点是子查询需要同时返回两种不同类型的列(ueb_uuid和MAX(version)),而非单一值,以此关联主表完成筛选。
你的尝试代码
Subquery<Integer> subquery = query.subquery(Integer.class); Root<ObjektEntity> subqueryRoot = subquery.from(ObjektEntity.class); subquery.select(builder.max(subqueryRoot.get(ObjektEntity_.version))); subquery.where(builder.equal(root.get(AnotherEntity_.objekt),objekt.get(ObjektEntity_.uuid) )); query.where(builder.equal(root.get(ObjektEntity_.VERSION),subquery));
解决方案
使用Tuple作为子查询的返回类型,同时承载ueb_uuid和最大版本号,再通过多条件关联主表:
CriteriaBuilder builder = session.getCriteriaBuilder(); CriteriaQuery<ObjektEntity> criteriaQuery = builder.createQuery(ObjektEntity.class); Root<ObjektEntity> root = criteriaQuery.from(ObjektEntity.class); // 构建子查询,返回包含ueb_uuid和max(version)的Tuple Subquery<Tuple> subquery = criteriaQuery.subquery(Tuple.class); Root<ObjektEntity> subRoot = subquery.from(ObjektEntity.class); // 子查询选择目标字段并分组 subquery.select(builder.tuple( subRoot.get(ObjektEntity_.ueb_uuid), builder.max(subRoot.get(ObjektEntity_.version)) )); subquery.groupBy(subRoot.get(ObjektEntity_.ueb_uuid)); // 主查询通过两个条件关联子查询,匹配ueb_uuid和对应最大版本 criteriaQuery.where(builder.and( builder.equal(root.get(ObjektEntity_.ueb_uuid), subRoot.get(ObjektEntity_.ueb_uuid)), builder.equal(root.get(ObjektEntity_.version), builder.max(subRoot.get(ObjektEntity_.version))) )); // 执行查询获取结果 List<ObjektEntity> latestVersionEntities = session.createQuery(criteriaQuery).getResultList();
关键说明
- 子查询返回类型:用
Tuple可以灵活承载多列不同类型的数据,适配ueb_uuid(如UUID/String)和version(Integer)的类型差异 - 多字段关联:通过
builder.and()组合两个等式,完全对齐原SQL中主表与子查询的关联逻辑 - 分组逻辑:子查询通过
groupBy(subRoot.get(ObjektEntity_.ueb_uuid))实现原SQL的分组取最大版本逻辑
内容的提问来源于stack exchange,提问作者verklixt
相关产品推荐
相关产品推荐

