一般的hibernate自定义字段多表查询时,返回的结果是object对象数组,这个对象数组没有办法直接映射为object对象,网上针对这个问题有一些解决方案。我这里记录一下我们项目组的另一种变相实现方式。个人觉得也挺好用的,没有网上说的那么复杂,具体实现如下:
首先是sql语句,sql语句定义要求返回一个键值对的map对象,下面是具体的定义例子:
StringBuffer hql = new StringBuffer();
hql.append(" select new map(a.activityName as activityName, p.projectName as projectName, ");
hql.append(" i.itemName as itemName, i.itemId as itemId, ");
hql.append(" i.projectId as projectId, i.activityId as activityId, ");
hql.append(" i.startDate as itemStartDate, i.endDate as itemEndDate, ");
hql.append(" (select count(*) from TbbsUserenrollitems e where e.itemId=i.itemId) as itemParticipantNum) ");
hql.append(" from TbbsItem i, TbbsProject p, TbbsActivityplan a where ");
hql.append(" i.projectId=p.projectId and p.activityId=a.activityId ");
这样定义的sql语句,使用hibernatetemplate执行之后,返回的将不会是一个list的object对象数组了,而是一个list的hashmap对象。然后再基于我们自定义的一个工具函数,具体实现如下:
public static Object assemble(Map<String, Object> objs, Class<?> targetClass) throws IllegalAccessException, InvocationTargetException, InstantiationException {
if (null == objs) {
return null;
}
Object target = targetClass.newInstance();
if (target != null) {
for(Map.Entry<String, Object> e : objs.entrySet()) {
BeanUtils.copyProperty(target, e.getKey(), e.getValue());
}
}
return target;
}
这里基于apache的beanutils工具提供的属性拷贝函数,依次调用hashmap里面的所有键值对,完成属性字段的映射。但是这里有一个要求就是这个字段必须和pojo类里面的字段名称是一样的(貌似大小写没有关系)。具体使用的例子如下:
ActivityMonitorDto amDto = (ActivityMonitorDto)ObjectUtil.assemble((Map<String, Object>)objs, ActivityMonitorDto.class);
这样就可以完成自定义字段查询和pojo的映射了。