【问题标题】:Hibernate Criteria with Projections.groupProperty cannot return full hibernate object (ClassCastException)带有 Projections.groupProperty 的休眠条件无法返回完整的休眠对象 (ClassCastException)
【发布时间】:2013-03-16 16:37:58
【问题描述】:

我对 Hibernate 比较陌生,在我的 hibernate 类上添加“不同”限制时遇到问题。

@Entity
public class TaggedOffer {
   private Long tagged_offers_id;
   private String brand;
   private Long cid;
   private Date created_date;
   //Getter and Setter and more fields
}

之前,我们按如下方式创建休眠查询:

public DetachedCriteria build(final TaggedOfferRequest request) {

        DetachedCriteria criteria = DetachedCriteria.forClass(TaggedOffer.class);

        criteria.add(Restrictions.eq("brand", request.getBrand()));
        criteria.add(Restrictions.in("cid", request.getCids()));

        // sort by date
        criteria.addOrder(Property.forName("createdDate").desc());

        return criteria;
}

这将创建以下(工作)SQL 查询:

select
        this_.tagged_offers_id as tagged1_2_3_,
        this_.brand as brand2_3_,
        this_.cid as cid2_3_,
        this_.created_date as created6_2_3_
    from
        site.tagged_offers this_ 
    where
        this_.brand=? 
        and this_.country_code=? 
        and this_.cid in (
            ?, ?
        ) 
    order by
        this_.created_date desc limit ?

这里是棘手的部分。我们现在需要确保返回的结果在 cid 字段上是不同的。意思是,返回尽可能多的结果,前提是每条记录都有一个与之关联的唯一 cid。

我在 SQL 中对此进行了研究,似乎最简单的方法就是在查询中添加一个 group by cid。就休眠标准而言,这基本上是我一直在尝试的:

public DetachedCriteria build(final TaggedOfferRequest request) {

        DetachedCriteria criteria = DetachedCriteria.forClass(TaggedOffer.class);

        criteria.add(Restrictions.eq("brand", request.getBrand()));
        criteria.add(Restrictions.in("cid", request.getCids()));

        // sort by date
        criteria.addOrder(Property.forName("createdDate").desc());

        // ** new ** distinct criteria
        criteria.setProjection(Projections.groupProperty("cid"));

        return criteria;
}

这几乎创建了我正在寻找的 SQL,但它稍后会引发类转换异常(因为它只是选择 cid 字段而不是整个对象)。

select
    this_.cid as y0_ 
from
    site.tagged_offers this_ 
where
    this_.brand=? 
    and this_.country_code=? 
    and this_.cid in (
        ?, ?
    ) 
    and tagtype1_.tag_type=? 
group by
    this_.cid 
order by
    this_.created_date desc limit ?

还有例外:

java.lang.ClassCastException: java.lang.Long cannot be cast to com.mycompany.site.taggedoffers.dao.model.TaggedOffer

知道如何使用投影来做我想做的事吗?

感谢您的帮助。

【问题讨论】:

    标签: java hibernate hibernate-criteria


    【解决方案1】:

    为您需要的所有列添加投影。

        ProjectionList projectionList = Projections.projectionList();
        projectionList.add(Projections.groupProperty("cid"));
        projectionList.add(Projections.property("tagged_offers_id"));
        ...
        criteria.setProjection(projectionList);
    

    【讨论】:

    • 根据 OP 问题,这不起作用:类转换异常仍将触发,因为返回的对象实际上是 Object[] 而不是 TaggedOffer。建议的答案可以用作“肮脏”的解决方法,它确实带回了TaggedOffer 将携带的所有值。我仍然对在投影后恢复原始 bean 类型而不是 Object 表的解决方案感兴趣......:/
    【解决方案2】:

    我怀疑为什么需要在这里使用 group by 而不进行任何聚合计算!

    如果您将 group by 与 projection 一起使用,则 group by 中使用的特定列将再次包含在 fetch sql 中,即使选择语句中已经使用了相同的列。

    要映射由于分组而由休眠生成的额外列,您必须在实体类中编写一个字段并将其标记为@Transient,或者您可以使用 setResultTransformer 并映射到另一个类

    【讨论】:

      猜你喜欢
      • 2011-01-10
      • 1970-01-01
      • 2016-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多