Hibernate + 2nd level cache bug

Recently, I have come across a nasty bug. When Hibernate executes a cacheable query and applying a ResultTransformer on a result of that query, java.lang.ClassCastException is thrown.

session.createCriteria(RateEntity.class)
  .add(Restrictions.eq(CURR_ID, criteria.getCurrency()))       
  .add(Restrictions.eq(TYPE, criteria.getRateType().name()))        
  .add(Restrictions.gt(TS_CRT, criteria.getFromTime().toDate()))         
  .setProjection(Projections.projectionList()            
  .add(Projections.property(TS_CRT), TIME_DTO_PROPERTY)             
  .add(Projections.property(RATE), RATE_DTO_PROPERTY))         
  .addOrder(Order.asc(TS_CRT))        
  .setCacheable(true)        
  .setResultTransformer(Transformers.aliasToBean(RateDTO.class))        
  .list();

It seems that the ResultTransformer is applied on the result before putting it into cache. Cache expects Object list but it receives transformed results (in this case RateDTO list). It cannot deal with it and as a result exception is thrown.

The bug is present in Hibernate 3.6.6.Final version.

One of the workarounds would be to remove

.setResultTransformer(Transformers.aliasToBean(RateDTO.class))

and allow query return Object list.

Having Object list they can be transformed manually to the desired list:

public static List transformToBean(Class resultClass, List < String > aliasList, List resultList) {
  if (CollectionUtils.isEmpty(aliasList)) {
    throw new IllegalArgumentException("aliasList is required");
  }
  if (CollectionUtils.isEmpty(resultList)) {
    return Collections.EMPTY_LIST;
  }

  List transformedList = new ArrayList();
  AliasToBeanResultTransformer aliasToBeanResultTransformer = new AliasToBeanResultTransformer(resultClass);
  Iterator it = resultList.iterator();
  Object[] obj;
  while (it.hasNext()) {
    obj = (Object[]) it.next();
    transformedList.add(aliasToBeanResultTransformer.transformTuple(obj, (String[]) aliasList.toArray()));
  }
  return transformedList;
}

Leave a Reply

Your email address will not be published. Required fields are marked *