Mryqu's Notes


  • 首页

  • 搜索
close

Hibernate3 HQL: ClassCastException解决办法

时间: 2013-06-11   |   分类: Service+JavaEE     |   阅读: 312 字 ~2分钟

下面的示例代码跑在Hibernate 3.6.8,会抛出异常java.lang.ClassCastException:[Ljava.lang.Object 无法转换成实体对象。通过调试可知返回的仍然是标量字段对象数组,而不是实体对象。

public class DemoEntity {
  public static final String DEMO_ENTITY_ID = "demoEntityID";
  public static final String USER_ID = "userID";
  public static final String OFFICE_ID = "officeID";
  
  private Integer demoEntityID;
  private String  userID;
  private Integer officeID;
  private String  subjectTxt;
  
  public List findDemoEntitys(int startID, int limit,
      boolean includeStartIdInResults)
  {
    try
    {
    StringBuilder querySb = new StringBuilder();
      querySb.append("select demo.").append(DemoEntity.DEMO_ENTITY_ID);     
      querySb.append(", demo.").append(DemoEntity.USER_ID);
      querySb.append(", demo.").append(DemoEntity.OFFICE_ID);
      querySb.append(" from DemoEntity demo where demo.").append(DemoEntity.DEMO_ENTITY_ID);
      if (includeStartIdInResults) {
        querySb.append(" >= ").append(startID);
      } else {
        querySb.append(" > ").append(startID);
      }
      querySb.append(" order by demo.").append(DemoEntity.DEMO_ENTITY_ID).append(" asc");
      Query query = sessionFactory.getCurrentSession().createQuery(querySb.toString());
      query.setResultTransformer(Transformers.aliasToBean(DemoEntity.class));
      query.setMaxResults(limit);
      List results = query.setCacheable(true).list();
      return results;
    }
    catch (RuntimeException re)
    {
      throw re;
    }
  }
}

通过分析Hibernate3.6.8源码,可知ClassicQueryTranslatorFactory使用了org.hibernate.hql.classic.QueryTranslatorImpl(继承自BasicLoader),它没有将标量字段数组转换成实体对象。

protected List getResultList(List results, ResultTransformer resultTransformer) 
throws QueryException {
  if ( holderClass != null ) {
    for ( int i = 0; i < results.size(); i++ ) {
      Object[] row = ( Object[] ) results.get( i );
      try {
        results.set( i, holderConstructor.newInstance( row ) );
      }
      catch ( Exception e ) {
        throw new QueryException( "could not instantiate: " + holderClass, e );
      }
    }
  }
  return results;
}

通过分析Hibernate3.6.8源码,可知ASTQueryTranslatorFactory则使用org.hibernate.hql.ast.QueryTranslatorImpl,它使用的是QueryLoader,而QueryLoader会将标量字段数组转换成实体对象。

protected List getResultList(List results, ResultTransformer resultTransformer) 
throws QueryException {
  // meant to handle dynamic instantiation queries...
  HolderInstantiator holderInstantiator = buildHolderInstantiator( resultTransformer );
  if ( holderInstantiator.isRequired() ) {
    for ( int i = 0; i < results.size(); i++ ) {
      Object[] row = ( Object[] ) results.get( i );
      Object result = holderInstantiator.instantiate(row);
      results.set( i, result );
    }

    if ( !hasSelectNew() && resultTransformer != null ) {
      return resultTransformer.transformList(results);
    }
    else {
      return results;
    }
  }
  else {
    returnresults;
  }
}

解决方案1:修改querytranslator factory 将Hibernate配置文件中hibernate.query.factory_class由org.hibernate.hql.classic.ClassicQueryTranslatorFactory修改为org.hibernate.hql.ast.ASTQueryTranslatorFactory,这样就能工作正常。 ClassicQueryTranslatorFactory是手写的传统HQL语法解析器工厂类,ASTQueryTranslatorFactory是更新的、基于ANTLR语法解析器生成的HQL语法解释器工厂类。

<propertyname="hibernate.query.factory_class"value="org.hibernate.hql.ast.ASTQueryTranslatorFactory"/>

解决方案2:不使用setResultTransformer函数,自己对结果进行转换

Query query = sessionFactory.getCurrentSession().createQuery(querySb.toString());
//query.setResultTransformer(Transformers.aliasToBean(DemoEntity.class));
query.setMaxResults(limit);
List<Object[]> queryRes = query.setCacheable(true).list();

List<DemoEntity> results = new ArrayList<DemoEntity>();        
if(queryRes!=null && !queryRes.isEmpty())
{
  String[] alias = {DemoEntity.DEMO_ENTITY_ID, DemoEntity.USER_ID, DemoEntity.OFFICE_ID);
  ResultTransformer resTransformer = Transformers.aliasToBean(DemoEntity.class);
  for(int i=0;i<queryRes.size();i++)
  {
     Object[] objs = (Object[]) queryRes.get(i);
     if(objs!=null)
     {
         results.add((DemoEntity) resTransformer.transformTuple(objs, alias));
     }
  }
}
return results;

标题:Hibernate3 HQL: ClassCastException解决办法
作者:mryqu
声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!

#hibernate# #hql# #ClassCastException# #ResultTransformer#
PostgreSQL JDBC setFetchSize
Hibernate3.X升级到4.X实践
  • 文章目录
  • 站点概览

Programmer & Architect

662 日志
27 分类
1472 标签
GitHub Twitter FB Page
© 2009 - 2023 Mryqu's Notes
Powered by - Hugo v0.120.4
Theme by - NexT
0%