解决HIbernate分页问题

HibernateCriteria分页产生的问题大家都知道做分页必须要知道总记录数,这就为我们出了一到小题儿,往往我们直接用Criteria调用list方法就返回全部查询结果了,但是分页必须在返回列表之前得到总行数。我之前的做法是写两个方法,参数完全一样,一个返回Integer,也就是记录数,一个返回List,结果集。这样写感觉挺麻烦的,还有人直接用criteria.list()返回记录数,再设置分页属性,那样还叫什么分页啊,调用list已经将数据加载到内存了,那不又成了内存分页,这种做法程序处理简单了,性能降下来了。

今天在网上闲逛发现了一个新招,代码如下(只贴出回调函数里的代码了):

灰色斜体为业务相关代码,请无视

publicObjectdoInHibernate(Sessionsession)throwsHibernateException,SQLException{

Criteriacriteria=session.createCriteria(XtLog.class);

CriteriauserCriteria=criteria.createCriteria("xtUser");

CriterialcCriteria=criteria.createCriteria("xtLogClass");

if(StringUtils.isNotBlank(userId)){

userCriteria.add(Restrictions.like("userId",userId,MatchMode.START));

}

if(StringUtils.isNotBlank(logClassId)){

lcCriteria.add(Restrictions.eq("logClassId",logClassId));

}

if(beginDate!=null&&endDate!=null){

criteria.add(Restrictions.between("xtOplogtime",beginDate,endDate));

}

inttotalRows=((Integer)criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();

psm.setTotalRows(totalRows);//业务代码,请无视

criteria.setProjection(null);

criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);

Map<String,String>orderMap=psm.getOrderMap();

if(orderMap!=null){

setOrder(criteria,userCriteria,lcCriteria,orderMap);

}

if(!psm.isAll()){//分页

criteria.setFirstResult(psm.getRowStart());

criteria.setMaxResults(psm.getPageSize());

}

//List<XtLog>logs=newArrayList<XtLog>();//返回日志列表

//List<Object[]>list=criteria.list();

//for(Object[]o:list){

//logs.add((XtLog)o[2]);

//}

//returnlogs;

returncriteria.list();

}

请注意绿色加粗那两行代码,那就是hibernate获取记录总行数的写法,直接和获取列表的方法写在一起,貌似很简洁,很给力,如果你查询的就是一张表,那么没事了,但我查询的日志是要关联到用户和日志分类的,最上面那三行代码就是关联了,这时发现返回到页面后报错了,原因是返回的并不是我要的日志List,而是Object[]的List,每个List里三个对象数组,主表的数组下标是最后一个,这时我就得使用蓝色字体的代码重新封装后返回,我感觉这样虽然解决了该问题,但还是不给力,不完美,不perfect,就是不爽,于是请将注意力转移到红色加粗字体上,写上它就OK了。

return (PageSupport) getHibernateTemplate().execute(
                new HibernateCallback() ...{
                    public Object doInHibernate(Session session)
                            throws HibernateException ...{
                        Criteria criteria = detachedCriteria
                                .getExecutableCriteria(session);
                        
                        CriteriaImpl impl = (CriteriaImpl) criteria;

                        //先把Projection和OrderBy条件取出来,清空两者来执行Count操作
                        Projection projection = impl.getProjection();
                        
                        logger.debug("SQL: " + Projections.rowCount());
                        
                        
                         
                        //执行查询
                        int totalCount = ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();

                        //将之前的Projection和OrderBy条件重新设回去
                        criteria.setProjection(projection);
                        if (projection == null) ...{
                            criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
                        }
                     
                        
                        
                        List items = criteria.setFirstResult(startIndex)
                        .setMaxResults(pageSize).list();
                
                        PageSupport ps = new PageSupport(items, totalCount,
                                pageSize, startIndex);
                        
                        return ps;
                    }
                }, true);

1、criteria.setProjection(null);

取得了总数后,为了能够再次取得对象列表。

2、detachedCriteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);

当hibernate采用关联的时候不使用这个返回的是个对象数组,加上这个返回的是当前列表的对象。

相关推荐