涉及 Hibernate 返回的 List<Object[]> 的 Java 类转换异常

Posted

技术标签:

【中文标题】涉及 Hibernate 返回的 List<Object[]> 的 Java 类转换异常【英文标题】:Java classcast exception which involves a List<Object[]> returned by Hibernate 【发布时间】:2011-10-07 20:54:29 【问题描述】:

首先,我正在维护一些不是我编写的代码,而且我对 Java 和 Hibernate 还很陌生。我最近调整了在 Hibernate 会话中运行的查询。返回类型没有改变(它仍然是一个列表),但我将查询从 session.createquery 更改为 session.createSQLquery。出于某种原因,这破坏了使用返回列表的代码。

消费方法如下:

public void getStuff(CompanyDAO company, ProductDAO dao, Long listingId, Long year, Long prodId, String startTag, String endAdFileTag, String letter) throws DAOException 
        List<Object[]> Products = dao.loadStuff(year, prodId, listingId, letter);

        if (Products != null && Products.size() > 0) 
            for (Object[] p : Products) 
                if (p != null) 
                    ProductListing parentChild = (ProductListing) p[0];
                    Long childCountObj = (Long) p[1];
                    int childCount = childCountObj.intValue();

                    if (parentChild != null) 
                        parentChild.setNextLevelChildrenCount(childCount);
                     
                
            
        
     

导致异常的是增强的 for 循环( for (Object[] p : Products) )。

这里有一个例外:java.lang.ClassCastException: ProductListing cannot be cast to [Ljava.lang.Object;

我不明白为什么更改查询会破坏这段代码。该查询返回一个对象数组,就像它在调整之前一样。

如果能对这个困惑有任何见解,我将不胜感激。

谢谢。

DAO 之前: public List loadStuff(Long year, Long prodId, Long listingId, String letter) throws DAOException 会话会话 = HibernateUtil.getSession(HibernateUtil.keys[sessionId]); StringBuffer strQuery = new StringBuffer(); if (year == null || prodId == null || ListingId == null ) return null;

    logger.debug("prodCode = " + prodId);
    logger.debug("year = " + year);


    strQuery.append("select pl, (select count(*) from ProductListing pppl where pppl.listingId = :listingid ");
    strQuery.append(" and pppl.responseYear = :year and pppl.parentProductId = pl.productId) as CHILD_COUNT ");
    strQuery.append(" from ProductListing pl ");
    strQuery.append(" where pl.parentProductId = :prodid ");
    strQuery.append(" and pl.responseYear = :year ");
    strQuery.append(" and pl.listingId = :listingid ");

    strQuery.append(" and (exists(select 0 from ProductListingMain plm, PdMain pm ");
    strQuery.append(" where plm.productListingId = pl.id ");
    strQuery.append(" and pm.currentVersionId = plm.versionId ");
    strQuery.append(" and pm.responded = 'Y' ");
    strQuery.append(" and pm.deleteFlag = 'N' ");
    strQuery.append(" and pm.onlineFlag = 'Y') ");
    strQuery.append(" or exists(select 0 from ProductListing ppl ");
    strQuery.append(" where ppl.listingId = :listingid ");
    strQuery.append(" and ppl.responseYear = :year ");
    strQuery.append(" and ppl.parentProductId = pl.productId)) ");

    //todo iclude the param letter in the query ... please test it before implementing
    if (letter != null) strQuery.append(" and upper (pl.onlineDescription) like '" + letter + "%' ");

    Query query = session.createQuery(strQuery.toString())
            .setLong("year", year)
            .setLong("prodid", prodId)
            .setLong("listingid", listingId);

    List list = query.list();
    return list;
  
DAO after:  

public List loadStuff(Long year, Long prodId, Long listingId, String letter) throws DAOException 会话会话 = HibernateUtil.getSession(HibernateUtil.keys[sessionId]); StringBuffer strQuery = new StringBuffer(); if (year == null || prodId == null || ListingId == null ) return null;

   String letterClause;
   if (letter != null) 
      letterClause = " and upper (pl.onlineDescription) like '" + letter + "%'  \n";
   else
      letterClause = " ";

   strQuery.append(
   " select pl.* \n" + 
   " from PRODUCT_LINE p, PRODUCT_LINE_X_LISTING pll, \n" + 
   "  PRODUCT_X_LISTING pl, CURRENT_YEAR cy, \n" + 
   "  LISTING l \n" + 
   " where p.id = pll.PRODUCT_LINE_ID \n" + 
   "  and p.prod_line_no = cy.PROD_LINE_MASTER  \n" +
   "  and pl.RESPONSE_YEAR = cy.ONLINE_YEAR \n" + 
   "  and pl.LISTING_ID = cy.LISTING_ID \n" + 
   "  and pll.LISTING_ID = l.id \n" + 
   "  and cy.LISTING_ID = l.id \n" + 
   "  and pll.YEAR = cy.ONLINE_YEAR \n" + 
   "  and p.Id = pll.product_line_id \n" + 
   "  and pl.PARENT_PRODUCT_ID = " + prodId + 
   "  and pl.LISTING_ID = " + listingId +
   "  and exists \n" +
           "   (select 'x' \n" + 
           "   from pd_product_listing_mv mv \n" +
           "   where mv.listing_id = pl.listing_id \n" +
           "     and mv.id = pl.id) \n" +
     letterClause +
   " order by upper(pl.ONLINE_DESCRIPTION) ");

    Query query = session.createSQLQuery(strQuery.toString())
     // return all columns in the ProductListing table, i.e. the entire class
       .addEntity("pl", com.acme.run.model.directories.ProductListing.class);
    List list = query.list();

    return list;

抱歉,这不是更好的格式。这是我的第一篇文章和

【问题讨论】:

显示您的 ProductDAO 界面。 查询在哪里?实际上,整个loadStuff() 方法。 【参考方案1】:

您只选择了pl.*,而您正在使用addEntity("pl", ProductListing.class),因此返回的列表是ProductListing 类型的对象。旧查询也选择了CHILD_COUNT,但不再选择。我想你忘记了新查询中的 COUNT 值。

【讨论】:

如果您对您的问题的答案感到满意(这是最佳答案并且该答案解决了问题),请将答案标记为“已接受”。【参考方案2】:

看起来将您的查询从“createquery”更改为 createsqlquery”会导致 Hiberate 返回一个 ProductListing 对象列表而不是 List

如果不查看 ProductDAO 就很难分辨 - 旧版本和新版本。

【讨论】:

以上是关于涉及 Hibernate 返回的 List<Object[]> 的 Java 类转换异常的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate HQL - query.list() 返回对象数组的对象数组

Hibernate HQL查询语句总结

Hibernate HQL查询 插入 更新(update)实例

动态(复杂)查询 JPA/Hibernate 上的动态参数

转: Hibernate HQL查询 插入 更新(update)实例

hibernate多表联合查询返回的list没有数据,但list.isEmpty()判断为啥不为真