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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:52:01