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

Hibernate JPA:如何查询transid去重的Orders实体

问题分析

你的代码抛出ClassCastException的原因很明确:cq.select(root.get("transid"))指定查询的是transid字段(String类型),但CriteriaQuery<Orders>声明要返回Orders实体,Hibernate无法将String类型的结果强制转换为Orders对象,因此报错。

解决方案

以下是几种实现“查询去重transid对应的Orders实体”的可行方式,你可以根据业务场景选择:

方案一:子查询获取去重transid,再查询对应实体

先通过子查询拿到所有去重的transid,再以此为条件查询完整的Orders实体,适用于一个transid对应多个实体且需要全部返回的场景:

public List<Orders> custOrder() {
    try (Session session = HibernateUtil.getSessionFactory().openSession()) {
        CriteriaBuilder cb = session.getCriteriaBuilder();
        
        // 子查询:获取所有去重的transid
        CriteriaQuery<String> subQuery = cb.createQuery(String.class);
        Root<Orders> subRoot = subQuery.from(Orders.class);
        subQuery.select(subRoot.get("transid")).distinct(true);
        
        // 主查询:根据去重的transid查询完整Orders实体
        CriteriaQuery<Orders> mainQuery = cb.createQuery(Orders.class);
        Root<Orders> mainRoot = mainQuery.from(Orders.class);
        mainQuery.select(mainRoot)
                 .where(mainRoot.get("transid").in(subQuery));
        
        return session.createQuery(mainQuery).getResultList();
    }
}

方案二:分组获取每组唯一实体

如果一个transid对应多个实体,但你只需要每组中的一个实体(比如取主键最大/最小的记录),可以用分组+聚合函数实现:

public List<Orders> custOrder() {
    try (Session session = HibernateUtil.getSessionFactory().openSession()) {
        CriteriaBuilder cb = session.getCriteriaBuilder();
        
        // 子查询:按transid分组,获取每组的Orders主键(假设id是主键字段)
        CriteriaQuery<Long> subQuery = cb.createQuery(Long.class);
        Root<Orders> subRoot = subQuery.from(Orders.class);
        subQuery.select(cb.max(subRoot.get("id"))) // 用max或min选择每组的一条记录
                .groupBy(subRoot.get("transid"));
        
        // 主查询:根据主键查询完整Orders实体
        CriteriaQuery<Orders> mainQuery = cb.createQuery(Orders.class);
        Root<Orders> mainRoot = mainQuery.from(Orders.class);
        mainQuery.select(mainRoot)
                 .where(mainRoot.get("id").in(subQuery));
        
        return session.createQuery(mainQuery).getResultList();
    }
}

方案三:直接对实体去重(仅适用于transid唯一的场景)

如果transid是业务唯一键,且相同transid的实体所有字段完全一致,或者你的Orders实体的equals和hashCode方法是基于transid实现的,可以直接对实体使用distinct:

public List<Orders> custOrder() {
    try (Session session = HibernateUtil.getSessionFactory().openSession()) {
        CriteriaBuilder cb = session.getCriteriaBuilder();
        CriteriaQuery<Orders> cq = cb.createQuery(Orders.class);
        Root<Orders> root = cq.from(Orders.class);
        
        cq.select(root).distinct(true);
        
        return session.createQuery(cq).getResultList();
    }
}

内容的提问来源于stack exchange,提问作者Daily JavaFX

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 16:55:32