hibernate如何根据传进去实体的不为空属性生成动态查询,并实现分页,经过查看hibernate api需要用到Criteria ,但是Criteria 有个缺点就是当另一个表A中某一外键列是该表B的主键,如果A表中有两条记录对应B表的某一主键,则查询结果中B表的该记录也会变为两条,我感到很不理解!最后从网上得知可以用 .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);去掉重复的结果,但实验之后我发现该语句只在提交的时候(也就是crit.list();的时候)才会去掉重复的结果,而分页的数据获取是在crit.list();之前,也就是说分页是在有重复数据的情况下根据起始位置获取的数据,显然是不正确的。后来又得知可以用crit .setProjection(Projections .projectionList()
.add(Projections .distinct(Projections .id()))的方法获得不重复的主键ID,可是Projections 只能指定属性,无法获得实体,最后只能用Projections 先获得id和创建时间(因为这里是按照创建时间排序的,所以查询结果中必须有创建时间),然后再根据ID查询实体,用 .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);去掉重复的结果;
List<ContentInfo> result = (List<ContentInfo>) getHibernateTemplate()
.execute(new HibernateCallback() {
public Object doInHibernate(Session arg0)
throws HibernateException, SQLException {
ContentInfo ci = new ContentInfo();
BUtil.QueryContentBean2ContentInfo(ci, instance);
//根据实体创建Example
Example example = Example.create(ci)
.excludeZeroes().ignoreCase() // perform
.enableLike(); // use like for string
Criteria crit = arg0.createCriteria(
ContentInfo.class).add(example).addOrder(
Order.desc("createtime"));
// .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
// 查询出满足查询条件的内容的不重复id和创建时间
crit .setProjection(Projections .projectionList()
.add(Projections .distinct(Projections .id()))
.add(Projections .property("createtime")));
// 设置分页的信息
crit.setFirstResult(PageUtil.getStart(currPage,
pageSize));
crit.setMaxResults(pageSize);
List contentList = crit.list();
//提取出满足查询条件的内容的不重复id
if (contentList != null
&& contentList.isEmpty() == false) {
List contentId = new ArrayList();
for (Object ob : contentList) {
Object[] obs = (Object[]) ob;
contentId.add(obs[0]);
}
// 通过内容id再取出内容实体
Criteria crit2 = arg0.createCriteria( ContentInfo.class)
.add( Restrictions.in("contentid",contentId)).addOrder( Order.desc("createtime"))
.setResultTransformer( Criteria.DISTINCT_ROOT_ENTITY);
List<ContentInfo> results = (List<ContentInfo>) crit2 .list();
log.debug("find by example successful, result size: "+ results.size());
return results;
} else {
return null;
}
}
});
注意:
如果实体的主键不为空是不参与动态生成查询条件;
如果实体的属性中有Long类型的,不要让它为0,要为null,否则就会生成查询条件where 属性***=0,所以有些时候你都不知道为什么查询出来的结果为空。当然在这里是可以控制,在生成example 的时候添加excludeZeroes(),就把0排斥了,但这样带来的缺点就是,如果你将某一个Long类型的属性设为0,期望动态生成where 属性***=0就不可能了。