使用Hibernate返回自定义类型时报错的问题

来源:互联网 发布:网络信息时代的利与弊 编辑:程序博客网 时间:2024/06/03 22:51

转载自:  http://blog.csdn.net/java_zys/article/details/68940691


数据库为oracle,在使用Hibernate查询时想要返回自定义的pojo类型,遇到类型转换的异常。如下面的命名查询希望返回数据行为typeClass类型

[java] view plain copy
  1. Query localQuery = session.getNamedQuery("findPersonInfo");  
  2. localQuery.setResultTransformer(Transformers.aliasToBean(typeClass)).list();//typeClass为目标pojo类型  

运行后报错,错误信息如下:

[java] view plain copy
  1. java.lang.ClassCastException: com.test.pojo.TestPojo cannot be cast to java.util.Map  
  2.     at org.hibernate.property.access.internal.PropertyAccessMapImpl$SetterImpl.set(PropertyAccessMapImpl.java:102)  
  3.     at org.hibernate.transform.AliasToBeanResultTransformer.transformTuple(AliasToBeanResultTransformer.java:78)  
  4.     at org.hibernate.hql.internal.HolderInstantiator.instantiate(HolderInstantiator.java:75)  
  5.     at org.hibernate.loader.custom.CustomLoader.getResultList(CustomLoader.java:434)  
  6.     at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430)  
  7.     at org.hibernate.loader.Loader.list(Loader.java:2425)  
  8.     at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:335)  
  9.     at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2153)  
  10.     at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:987)  
  11.     at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:148)  
  12.     at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1410)  
TestPojo类如下:

[java] view plain copy
  1. public class TestPojo {  
  2.     private String id;  
  3.     private String username;  
  4.     public String getId() {  
  5.         return id;  
  6.     }  
  7.     public void setId(String id) {  
  8.         this.id = id;  
  9.     }  
  10.     public String getUsername() {  
  11.         return username;  
  12.     }  
  13.     public void setUsername(String username) {  
  14.         this.username = username;  
  15.     }  
  16. }  


原因是使用oracle时返回的字段默认为大写,导致转换失败。Hibernate可以通过自定义ResultTransformer类来解决这个问题,给出参考代码:

[java] view plain copy
  1. import java.lang.reflect.Field;  
  2. import java.util.List;  
  3. import org.apache.commons.beanutils.BeanUtilsBean;  
  4. import org.hibernate.HibernateException;  
  5. import org.hibernate.transform.ResultTransformer;  
  6.   
  7. /** 
  8.  *  
  9.  * 修正hibernate返回自定义pojo类型时找不到属性的BUG 
  10.  * 主要发生在使用oracle时,查询返回的字段默认是大写的(除非SQL中指定了别名),这导致返回自定义pojo类型时会报找不到属性的错误,该类用于修正此BUG。 
  11.  * 使用该类时SQL返回的字段名大小写或者带"_"都会被忽略,如数据库字段为 USER_NAME,自定义pojo的属性名为username就可以使用 
  12.  *  
  13.  * 
  14.  */  
  15. public class IgnoreCaseResultTransformer implements ResultTransformer {  
  16.   
  17.     private static final long serialVersionUID = -3779317531110592988L;  
  18.   
  19.     private final Class<?> resultClass;  
  20.     private Field[] fields;  
  21.     private BeanUtilsBean beanUtilsBean;  
  22.   
  23.     public IgnoreCaseResultTransformer(final Class<?> resultClass) {  
  24.         this.resultClass = resultClass;  
  25.         this.fields = this.resultClass.getDeclaredFields();  
  26.         beanUtilsBean=BeanUtilsBean.getInstance();  
  27.     }  
  28.   
  29.     /** 
  30.      * aliases为每条记录的数据库字段名,ORACLE字段名默认为大写 
  31.      * tupe为与aliases对应的字段的值 
  32.      */  
  33.     public Object transformTuple(final Object[] tuple, final String[] aliases) {  
  34.         Object result;  
  35.         try {  
  36.             result = this.resultClass.newInstance();  
  37.             for (int i = 0; i < aliases.length; i++) {  
  38.                 for (Field field : this.fields) {  
  39.                     String fieldName = field.getName();  
  40.                     //数据库字段带下划线的时候也能保证使用,如数据库字段为 USER_NAME,自定义pojo的属性名为username就可以使用  
  41.                     if (fieldName.equalsIgnoreCase(aliases[i].replaceAll("_"""))) {  
  42.                         beanUtilsBean.setProperty(result, fieldName, tuple[i]);  
  43.                         break;  
  44.                     }  
  45.                 }  
  46.             }  
  47.         } catch (Exception e) {  
  48.             throw new HibernateException("Could not instantiate resultclass: " + this.resultClass.getName(), e);  
  49.         }  
  50.         return result;  
  51.     }  
  52.   
  53.     @SuppressWarnings("rawtypes")  
  54.     public List transformList(final List collection) {  
  55.         return collection;  
  56.     }  
  57. }  

使用方法:

[java] view plain copy
  1. Query localQuery = paramSession.getNamedQuery("findPersonInfo");  
  2. localQuery.setResultTransformer(new IgnoreCaseResultTransformer(typeClass)).list();//typeClass为目标pojo类型  
原创粉丝点击