数据库为oracle,在使用Hibernate查询时想要返回自定义的pojo类型,遇到类型转换的异常。如下面的命名查询希望返回数据行为typeClass类型
query.setResultTransformer(Transformers.aliasToBean(McnInfoVo.class));
return query.getResultList();
运行后报错,错误信息如下:
McnInfoVo类如下:
@Data
public class McnInfoVo implements Serializable {
private static final long serialVersionUID = -621560689577743929L;
/**
* 节目ID
*/
private String programId;
/**
* 投放渠道
*/
private String disposeChannel;
/**
* 应用渠道
*/
private String applyChannel;
/**
* 开始时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime startTime;
/**
* 结束时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime endTime;
/**
* 操作人账号
*/
private String operator;
/**
* 操作人昵称
*/
private String operatorName;
/**
* 阶段状态
*/
private String nodeStatus;
}
原因是使用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.setResultTransformer(new IgnoreCaseResultTransformer(McnInfoVo.class));
return query.getResultList();
完美解决!