使用Hibernate返回自定义类型时报错的问题
2017-04-01 08:57
1841 查看
数据库为oracle,在使用Hibernate查询时想要返回自定义的pojo类型,遇到类型转换的异常。如下面的命名查询希望返回数据行为typeClass类型
运行后报错,错误信息如下:
原因是使用oracle时返回的字段默认为大写,导致转换失败。Hibernate可以通过自定义ResultTransformer类来解决这个问题,给出参考代码:
import java.lang.reflect.Field;
import java.util.List;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.hibernate.HibernateException;
import org.hibernate.transform.ResultTransformer;
/**
*
* 修正hibernate返回自定义pojo类型时找不到属性的BUG
* 主要发生在使用oracle时,查询返回的字段默认是大写的(除非SQL中指定了别名),这导致返回自定义pojo类型时会报找不到属性的错误,该类用于修正此BUG。
* 使用该类时SQL返回的字段名大小写或者带"_"都会被忽略,如数据库字段为 USER_NAME,自定义pojo的属性名为username就可以使用
*
*
*/
public class IgnoreCaseResultTransformer implements ResultTransformer {
private static final long serialVersionUID = -3779317531110592988L;
private final Class<?> resultClass;
private Field[] fields;
private BeanUtilsBean beanUtilsBean;
public IgnoreCaseResultTransformer(final Class<?> resultClass) {
this.resultClass = resultClass;
this.fields = this.resultClass.getDeclaredFields();
beanUtilsBean=BeanUtilsBean.getInstance();
}
/**
* aliases为每条记录的数据库字段名,ORACLE字段名默认为大写
* tupe为与aliases对应的字段的值
*/
public Object transformTuple(final Object[] tuple, final String[] aliases) {
Object result;
try {
result = this.resultClass.newInstance();
for (int i = 0; i < aliases.length; i++) {
for (Field field : this.fields) {
String fieldName = field.getName();
//数据库字段带下划线的时候也能保证使用,如数据库字段为 USER_NAME,自定义pojo的属性名为username就可以使用
if (fieldName.equalsIgnoreCase(aliases[i].replaceAll("_", ""))) {
beanUtilsBean.setProperty(result, fieldName, tuple[i]);
break;
}
}
}
} catch (Exception e) {
throw new HibernateException("Could not instantiate resultclass: " + this.resultClass.getName(), e);
}
return result;
}
@SuppressWarnings("rawtypes")
public List transformList(final List collection) {
return collection;
}
}
使用方法:
参考:https://hibernate.atlassian.net/browse/HHH-5815
Query localQuery = session.getNamedQuery("findPersonInfo"); localQuery.setResultTransformer(Transformers.aliasToBean(typeClass)).list();//typeClass为目标pojo类型
运行后报错,错误信息如下:
java.lang.ClassCastException: com.test.pojo.TestPojo cannot be cast to java.util.Map at org.hibernate.property.access.internal.PropertyAccessMapImpl$SetterImpl.set(PropertyAccessMapImpl.java:102) at org.hibernate.transform.AliasToBeanResultTransformer.transformTuple(AliasToBeanResultTransformer.java:78) at org.hibernate.hql.internal.HolderInstantiator.instantiate(HolderInstantiator.java:75) at org.hibernate.loader.custom.CustomLoader.getResultList(CustomLoader.java:434) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430) at org.hibernate.loader.Loader.list(Loader.java:2425) at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:335) at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:2153) at org.hibernate.internal.AbstractSharedSessionContract.list(AbstractSharedSessionContract.java:987) at org.hibernate.query.internal.NativeQueryImpl.doList(NativeQueryImpl.java:148) at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1410)TestPojo类如下:
public class TestPojo { private String id; private String username; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } }
原因是使用oracle时返回的字段默认为大写,导致转换失败。Hibernate可以通过自定义ResultTransformer类来解决这个问题,给出参考代码:
import java.lang.reflect.Field;
import java.util.List;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.hibernate.HibernateException;
import org.hibernate.transform.ResultTransformer;
/**
*
* 修正hibernate返回自定义pojo类型时找不到属性的BUG
* 主要发生在使用oracle时,查询返回的字段默认是大写的(除非SQL中指定了别名),这导致返回自定义pojo类型时会报找不到属性的错误,该类用于修正此BUG。
* 使用该类时SQL返回的字段名大小写或者带"_"都会被忽略,如数据库字段为 USER_NAME,自定义pojo的属性名为username就可以使用
*
*
*/
public class IgnoreCaseResultTransformer implements ResultTransformer {
private static final long serialVersionUID = -3779317531110592988L;
private final Class<?> resultClass;
private Field[] fields;
private BeanUtilsBean beanUtilsBean;
public IgnoreCaseResultTransformer(final Class<?> resultClass) {
this.resultClass = resultClass;
this.fields = this.resultClass.getDeclaredFields();
beanUtilsBean=BeanUtilsBean.getInstance();
}
/**
* aliases为每条记录的数据库字段名,ORACLE字段名默认为大写
* tupe为与aliases对应的字段的值
*/
public Object transformTuple(final Object[] tuple, final String[] aliases) {
Object result;
try {
result = this.resultClass.newInstance();
for (int i = 0; i < aliases.length; i++) {
for (Field field : this.fields) {
String fieldName = field.getName();
//数据库字段带下划线的时候也能保证使用,如数据库字段为 USER_NAME,自定义pojo的属性名为username就可以使用
if (fieldName.equalsIgnoreCase(aliases[i].replaceAll("_", ""))) {
beanUtilsBean.setProperty(result, fieldName, tuple[i]);
break;
}
}
}
} catch (Exception e) {
throw new HibernateException("Could not instantiate resultclass: " + this.resultClass.getName(), e);
}
return result;
}
@SuppressWarnings("rawtypes")
public List transformList(final List collection) {
return collection;
}
}
使用方法:
Query localQuery = paramSession.getNamedQuery("findPersonInfo"); localQuery.setResultTransformer(new IgnoreCaseResultTransformer(typeClass)).list();//typeClass为目标pojo类型
参考:https://hibernate.atlassian.net/browse/HHH-5815
相关文章推荐
- 使用Hibernate返回自定义类型时报错的问题
- 使用自定义JavaScriptConverter返回自定义的复杂类型
- 使用Hibernate轻松解决java中date与datetime类型不兼容的问题
- hibernate中自定义数据类型的使用---UserType,CompositeUserType接口的使用
- 使用泛型解决需要动态返回类型的问题
- (转载)PHP使用empty检查函数返回结果时报Fatal error: Can't use function return value in write context的问题
- 解决hibernate中不能正常使用blog类型字段上传数据的问题
- hibernate3使用c3p0连接池调用oracle自定义对象问题处理
- 使用mssql2008新特性(存储过程参数类型使用"用户自定义表"来实现批量DML更新多表)解决项目里遇到的性能问题
- 使用findViewById查找自定义view时返回NULL问题
- 使用泛型解决需要动态返回类型的问题
- Hibernate使用自定义类型UserType映射Oracle的Date类型
- Hibernate中使用自定义insert,update,delete语句需要注意的问题
- Nhibernate使用HQL返回自定义类型
- c#关于数据库自定义类型在存储过程中返回服务器端的问题
- PHP使用empty检查函数返回结果时报Fatal error: Can't use function return value in write context的问题
- 在使用Hibernate时,因为一个查询需要更多的表连接而要使用SQL来解决性能问题。然而返回的结果集中包含了没有映射的Entity类中的表字段,在这个SQL中还有使用如何将层次关系的父子结点显示为横行
- 关于Column '*' not found 解决方案 Hibernate使用SQL查询返回实体类型,即返回某个类,或实体类
- PHP使用empty检查函数返回结果时报Fatal error: Can't use function return value in write context的问题
- Hibernate使用sql语句查询,返回实体类型的方法及注意事项