如何用Hibernate Criteria去除同COLOR属性重复的对象?
实现方案
方法一:子查询分组+主查询匹配(兼容性最优)
核心思路是先通过子查询获取每个color对应的唯一标识(比如最小的id),再基于这些标识查询完整的User对象,确保每个color只返回一条数据。
代码示例:
// 子查询:按color分组,取每组最小的id(也可换成max,按需选择保留哪条数据) DetachedCriteria subQuery = DetachedCriteria.forClass(User.class) .setProjection(Projections.projectionList() .add(Projections.min("id")) .add(Projections.groupProperty("color"))); // 主查询:筛选id在子查询结果中的User Criteria criteria = SrvDataAccess.getCurrentSession().createCriteria(User.class) .add(Subqueries.propertyIn("id", subQuery)); List<User> result = criteria.list();
方法二:Distinct投影+结果转换(Hibernate 5.2+适用)
如果你的Hibernate版本在5.2及以上,可以直接通过投影指定所有需要返回的字段,配合distinct去重,再转成User实体。
代码示例:
Criteria criteria = SrvDataAccess.getCurrentSession().createCriteria(User.class) .setProjection(Projections.distinct(Projections.projectionList() .add(Projections.property("id"), "id") .add(Projections.property("name"), "name") .add(Projections.property("age"), "age") .add(Projections.property("color"), "color"))) .setResultTransformer(Transformers.aliasToBean(User.class)); List<User> result = criteria.list();
注意:必须把所有需要返回的字段都加入投影,否则实体属性会缺失;不同数据库对多字段distinct的处理有差异,需要测试验证。
方法三:HQL辅助实现(可选补充)
如果觉得Criteria写法繁琐,也可以用HQL实现相同逻辑,思路和方法一一致:
String hql = "SELECT u FROM User u WHERE u.id IN (SELECT MIN(u2.id) FROM User u2 GROUP BY u2.color)"; List<User> result = SrvDataAccess.getCurrentSession().createQuery(hql, User.class).list();
额外说明
- 方法一的兼容性最好,适配绝大多数Hibernate版本,且不会出现属性丢失问题,优先推荐。
- 选择
MIN(id)还是MAX(id),取决于你想保留每组中的哪一条数据(比如id自增的话,MIN对应最早创建的记录,MAX对应最新的)。
内容的提问来源于stack exchange,提问作者SLSofiane
相关产品推荐
相关产品推荐

