1.思路
使用自写sql进行查询不需要在实体上添加@ManyToOne等注解,清晰简单并且容易实现。由于本例中要使用到limit子句进行分页,而hql不支持limit。因此使用原生sql不能直接使用new语句。需将返回值设为Object[]或者List<Object[]>类型,其中object数组中的每个元素都是查询出来的列,只需要在service层进行类型转换即可。
2.代码
(1).Dao代码
//多表查询获得articleMin
@Query(nativeQuery=true,value="select a.aid,a.title,a.summary,a.time,a.uid,a.uname,img,a.likenum,a.commentnum from article a,user u where a.uid=u.uid and a.sectionId=?1 limit ?2,?3")
List<Object[]> getArticleMin(int category,int curPage,int pageSize);
(2).Service代码
1.简单版转换List<Object[]> 转换成 List<特定类型>
List<Object[]> objects = articleMapper.getArticleMin(category,pageNum,pageSize);
List<ArticleMin> lists = new ArrayList<>();
ArticleMin articleMin;
for (Object[] object : objects) {
articleMin = new ArticleMin((Integer)object[0],(String)object[1],(String)object[2],(Date)object[3],(Integer)object[4],(String)object[5],(String)object[6],(Integer)object[7],(Integer)object[8]);
lists.add(articleMin);
}
2.利用反射List<Object[]> 转换成 List< T >类型
public static <T> List<T> transObjectsToBean(List<Object[]> objList, Class<T> clz) {
if(objList==null || objList.size()==0) {
return null;
}
//cz保存与参数长度相同的构造器参数
Class<?>[] cz = null;
//获取所有的构造方法
Constructor<?>[] cons = clz.getConstructors();
//找到构造方法与参数匹配的构造器参数
for(Constructor<?> ct : cons) {
Class<?>[] clazz = ct.getParameterTypes();
if(objList.get(0).length == clazz.length) {
//保存参数
cz = clazz;
break;
}
}
List<T> list = new ArrayList<T>();
for(Object[] obj : objList) {
Constructor<T> cr = null;
try {
//根据参数获取构造器类型
cr = clz.getConstructor(cz);
//利用匹配的构造器实例化对象
list.add(cr.newInstance(obj));
} catch (Exception e) {
e.printStackTrace();
}
}
return list;
}
注意:必须要加上nativeQuery=true否则使用的是hql不能使用limit子句,如果不使用limit子句可以使用hql,则可以在hql中new 一个实体,则无需返回object[]类型,如下所示:
@Query(value="select new 全限定类名.ArticleMin(a.aid,a.title,a.summary,a.time,a.uid,a.uname,img,a.likenum,a.commentnum) from Article a,User u where a.uid=u.uid and a.sectionId=?")
List<ArticleMin> getArticleMin(int category);