如何用Hibernate Criteria查询去重并返回完整Cat实体?
解决Hibernate Criteria查询返回无重复id的Cat实体列表问题
嘿,这个坑我太熟了!你现在遇到的问题核心在于:一旦给Criteria设置了Projection,Hibernate就只会返回你指定投影的字段集合,而不是完整的实体对象——所以你加了Projections.distinct(Projections.property("id"))之后,查询结果就变成了纯id的列表,自然没法得到完整的Cat实体。
下面给你几个可行的解决方案:
方法一:使用DISTINCT_ROOT_ENTITY结果转换器
这是最直接的方式,Hibernate专门提供了Criteria.DISTINCT_ROOT_ENTITY来处理根实体去重的场景,不需要额外的Projection:
List<Cat> results = (List<Cat>) session.createCriteria(Cat.class) .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY) .list();
这个转换器会自动根据实体的equals()和hashCode()方法来过滤重复的Cat对象,所以记得要给你的Cat类正确实现这两个方法(基于id字段即可):
import java.util.Objects; class Cat { long id; String name; int age; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Cat cat = (Cat) o; return id == cat.id; } @Override public int hashCode() { return Objects.hash(id); } }
方法二:改用HQL查询
如果你觉得Criteria用着不顺手,也可以直接写HQL语句,用DISTINCT关键字实现去重:
String hql = "SELECT DISTINCT c FROM Cat c"; List<Cat> results = session.createQuery(hql, Cat.class).list();
这种方式同样依赖Cat类的equals()和hashCode()实现,效果和第一种方法一致。
为什么原来的方法不行?
再帮你理一下逻辑:当你添加Projection后,Hibernate生成的SQL会变成SELECT DISTINCT id FROM cat,查询结果只有id列,所以list()返回的是List<Long>,你强制转成List<Cat>不仅得不到实体,还可能抛出类型转换异常——这就是为什么你只能看到id列表的原因。
内容的提问来源于stack exchange,提问作者Combo
相关产品推荐
相关产品推荐

