4、OA分页设计

来源:互联网 发布:哪个运营商的4g网络好 编辑:程序博客网 时间:2024/05/13 23:47

分页设计思路

 

JSP中与分页相关的信息

l 要显示本页的数据列表

•   使用<s:iterator value=“%{recordList}”>循环显示

l 要显示分页信息,包括:

•   当前页码、总页码数、每页显示多少条、总记录数

•   页码列表,只显示当前页附近的10个页码

•  

recordList      本页的数据列表

currentPage     当前页

pageCount       总页数

pageSize        每页显示多少条数据

recordCount      总记录数

beginPageIndex  页码列表的开始索引

endPageIndex    页码列表的结束索引

 
快速转到功能:使用下拉列表显示所有的页码,选中某页码后就转到相应的页面

 

 

 

 

 

 

使用Hibernate获取分页的数据

l  在Hibernate中获取一段数据的方式是:

•   Query.setFirstResult(int)

•   Query.setMaxResults(int)

 

举例:假设共有25条数据,每页显示10条(pageSize=10),则总共3页,获取每页数据的firstResult与maxResult分别为:

•   第1页:first=0,max=10

•   第2页:first=10,max=10

•   第3页:first=20,max=10

 

l  公式说明:

•   计算firstResult的公式为:(当前页-1) * pageSize

•   maxResults就是pageSize的值

 

 

总页数及页码列表的开始与结束索引的计算方法

l  计算总页码数pageCount的方式为:

•   方式1:recordCount / pageSize,如果有余数,就再加1页

•   方式2:(recordCount + pageSize - 1) / pageSize

l  计算beginPageIndex与endPageIndex(最多显示当前页附近的10个页码)

•   总页数小于等于10页,则全部显示

•   总页数大于10页

•   默认显示当前页附件近的10个页码(前4个 + 当前页 + 后5个)

•   前面不足4个页码时,就显示前10个页码

•   后面不足5个页码时,就显示后10个页码


一、   基本分页

 



topicAction/show.jsp

=========分页的信息 ==========

页次:${currentPage}/{pageCount}页  

每页显示:${pageSize}条  

总记录数:${recordCount}条 

 

<s:iteratorbegin="%{beginPageIndex}" end="%{endPageIndex}"var="num">

         ${num}

</s:iterator>

 

 

转到:  

         <select id="pn"onchange="gotoPage(this.value)">

                   <s:iteratorbegin="1" end="%{pageCount}" var="num"> 

                            <optionvalue="${num}">${num}</option>

                   </s:iterator>

         </select>

 

<script>

functiongotoPage( pageNum ){

window.location.href="xxx.action?pageNum=" + pageNum;

}

</script>

TopicAction

 

/** 显示单个主题(主帖 +回帖列表) */

 public String show()throws Exception{

        //准备数据

        //Topic

        Topic topic=topicService

        .getById(model.getId());

       

        ActionContext.getContext()

        .put("topic", topic);

           

        PageBean pageBean=replyService

        .getPageBean(pageNum,topic);

       

        ActionContext.getContext()

        .getValueStack().push(pageBean);                                                  

        return "show";

}

                                                        

ReplyServiceImpl

 

public PageBean getPageBean(int pageNum, Topic topic){

       

        int pageSize=Configuration.getPageSize();

        //查询本页的数据列表

        List list=getSession().createQuery(//

       "FROM Reply r WHERE r.topic=?

        ORDER BY r.postTime")

       .setParameter(0, topic)

       .setFirstResult((pageNum-1)*pageSize)

                .setMaxResults(pageSize)

                .list();

       

        // 查询总记录数

        Long recordCount=(Long) getSession()

        .createQuery(//

        "SELECT count(*) FROM

         Reply r WHERE r.topic=?")

                .setParameter(0, topic)

                .uniqueResult();

           

        return new PageBean(pageNum, pageSize,

        recordCount.intValue(), list);

    }

 


 

各种数据列表查询,不同的只是HQL与其中的参数列表,所以把这两个信息作为参数传到公共方法中就可以了,其中HQL

只需要传递“查询数据列表”的就行,要想查询总记录数,直接在这个HQL前面加上“select count(*)”就可以得到查询总数量的HQL语句。所以,设计的方法如下:

public class PageBean {

 

    // 传递的参数或是配置的参数

    private int currentPage;         //当前页

    private int pageSize;            //每页显示多少条记录

 

    // 查询数据库

    private int recordCount;         //总记录数

    private List recordList ;        //本页的数据列表

 

    //計算

    private int pageCount;           //总页数

    private int beginPageIndex;      //页码列表的开始索引(包含)

    private int endPageIndex;        //页码列表的结束索引(包含)

   

    /**

     * 只接受4个必要的属性,会自动的计算出其他3个属性的值

     * @param currentPage

     * @param pageSize

     * @param recordCount

     * @param recordList

     */

    public PageBean(int currentPage,int pageSize,int recordCount, List recordList){

       

        this.currentPage= currentPage;

        this.pageSize= pageSize;

        this.recordCount= recordCount;

        this.recordList= recordList;

        //计算总页数

        pageCount=(recordCount+pageSize-1)/pageSize;

       

        // 计算 beginPageIndex endPageIndex

        // >> 总页码小于等于10页时,全部显示

        if(pageCount<10){

            beginPageIndex=1;

            endPageIndex=pageCount;

        }

        // >> 总页码大于10页时,就只显示当前页附近的共10个页码

        else{

            // 默认显示4 +当前页 + 5

            beginPageIndex=currentPage-4;

            endPageIndex=currentPage+5;

            // 如果前面不足4个页码时,则显示前10

            if(beginPageIndex<1){

                beginPageIndex=1;

                endPageIndex=10;

            }

            // 如果后面不足5个页码时,则显示后10

            else if(endPageIndex>pageCount){

                endPageIndex=pageCount;

                beginPageIndex=endPageIndex-9;

            }

        }

    }

ForumAction中:

 

//准备主题列表的分页信息(使用公共的方法 +过滤与排序)

    String hql="FROM Topic t WHERE t.forum=?";

    List<Object> parameters=new ArrayList<Object>();

    parameters.add(forum);

   

   

    // >>过滤条件

    if(viewType==1){ // 1表示只看精华帖

        hql += " AND t.type=? ";

        parameters.add(Topic.TYPE_BEST);

    }

   

    // >> 排序条件

    if(orderBy==0){      //默认排序

        hql+="ORDER BY (CASE t.type WHEN 2 THEN 2 ELSE0 END) DESC, t.lastUpdateTime DESC";

    }

    else if(orderBy ==1){ //1代表只按最后更新时间排序<br>

        hql+="ORDER BY t.lastUpdateTime "+(asc?"ASC":"DESC");

    }

    else if(orderBy ==2){   // 2代表只按主题发表时间排序<br>

        hql+="ORDER BY t.postTime "+(asc?"ASC":"DESC");

    }

    else if(orderBy ==3){   // 3代表只按回复数量排序

        hql+="ORDER BY t.replyCount "+(asc?"ASC":"DESC");

    }

 

    PageBean pageBean=topicService.getPageBean(pageNum, hql, parameters.toArray());

    ActionContext.getContext().getValueStack().push(pageBean);

 

-----------------------------------------------------------------------------------------------------------------------------------------------------

 

BaseDaoImpl中:

 

public PageBean getPageBean(int pageNum, String queryListSQL,Object[] parameters) {

    int pageSize=Configuration.getPageSize();

   

    //查询本页的数据列表

    Query listQuery=getSession().createQuery(queryListSQL);

    if(parameters!=null && parameters.length>0){

        for(int i=0;i<parameters.length;i++){

            listQuery.setParameter(i, parameters[i]);

        }

    }

    listQuery.setFirstResult((pageNum-1)*pageSize);

    listQuery.setMaxResults(pageSize);

    List list=listQuery.list();    

   

    // 查询总记录数

    Query countQuery=getSession().createQuery("SELECT count(*) "+queryListSQL);

   

    if(parameters!=null && parameters.length>0){

        for(int i=0;i<parameters.length;i++){

            countQuery.setParameter(i, parameters[i]);

        }

    }

    Long recordCount=(Long) countQuery.uniqueResult();

       

    return new PageBean(pageNum, pageSize, recordCount.intValue(), list);

}

 

 

===========================================================================================

三、优化

如果有一个辅助生成HQL的工具类HqlHelper(后面页有详细说明),他的作用是持有HQL与参数列表。则这个获取分页信息的公共方法可以设计为:

其中:

    HqlHelper.getQueryListHql()      获取生成的查询数据列表的HQL

    HqlHelper.getQueryCountHql()     获取生成的查询总数量的HQL(没有OrderBy子句)

HqlHelper.getParameters()           获取参数列表

 

l 我们所用的查询数据列表的HQL一般的格式如下:
FROM 实体 WHERE条件1 AND 条件2 AND ... AND 条件n ORDER BY 属性1, 属性2, ..., 属性n”

l 说明:

•    From子句必须要有

•    Where子句是可选的

•    OrderBy子句是可选的

 

l  说明2:

•    Where子句中的多个条件之间是AND的关系,因为使用的场景都是数据列表的过滤,例如用户列表可以按姓名、性别、生日范围等条件过滤,如果指定了多个条件,这多个条件之间都是AND的关系。

•    Where子句中的表达式中可能0或多个参数:

•   没有参数的例子:t.forum IS NULL

•   1个参数的例子:t.id=?

•   2个参数的例子:t.id BETWEEN ? AND ?

•    

 

 

HqlHelper的设计:

public class HqlHelper {

    private String fromClause;

    private String whereClause="";

    private String orderByClause="";

    private List<Object> parameters=new ArrayList<Object>();

   

    /**

     * 生成From字句,默认别名为"o"

     * @param clazz

     */

    public HqlHelper(Class clazz){

        this.fromClause="FROM "+ clazz.getSimpleName()+" o";

    }

   

    /**

     * 生成From字句,默认别名为"o"

     * @param clazz

     */

    public HqlHelper(Class clazz,String alias){

        this.fromClause="FROM "+ clazz.getSimpleName()+" "+alias;

    }

   

    /**

     * 拼接where字句

     * @param condition

     * @param params

     * @return

     */

    public HqlHelper addCondition(String condition,Object...params){

        //拼接

        if(whereClause.length()==0){

            whereClause=" WHERE "+ condition;

        }else{

            whereClause+=" AND "+ condition;

        }

        // 保存参数

        if(params!=null && params.length>0){

            for(Object obj:params){

                parameters.add(obj);

            }

        }

        return this;

    }

   

    /**

     * 如果第1个参数为true,则拼接Where子句

     *

     * @param append

     * @param condition

     * @param params

     * @return

     */

    public HqlHelper addCondition(boolean append,String condition,Object...params){

        if(append){

            addCondition(condition, params);

        }

        return this;

    }

    /**

     * 拼接order by字句

     * @param propertyName

     * @param isAsc

     * @return

     */

    public HqlHelper addOrder(StringpropertyName,boolean isAsc){

        if(orderByClause.length()==0){

            orderByClause=" ORDER BY "+propertyName+(isAsc?" ASC":" DESC");

        }else{

            orderByClause+=", "+propertyName+(isAsc?" ASC":" DESC");

        }

        return this;

    }

   

    /**

     * 拼接order by字句

     * @param propertyName

     * @param isAsc

     * @return

     */

    public HqlHelper addOrder(boolean append,String propertyName,boolean isAsc){

        if(append){

            addOrder(propertyName, isAsc);

        }

        return this;

    }

   

    /**

     * 获取生成的查询数据列表的HQL语句

     * @return

     */

    public String getQueryListHql(){

        return fromClause+ whereClause+ orderByClause;

    }

   

    /**

     * 获取生成的查询数据列表的HQL语句

     * @return

     */

    public String getQueryCountHql(){

        return "SELECT count(*) "+fromClause+ whereClause;

    }

 

    /**

     * 获取参数列表,与HQL过滤条件中的'?'一一对应

     * @return

     */

    public List<Object> getParameters(){

        return parameters;

    }

   

    public HqlHelper buildPageBeanForStruts2(int pageNum, BaseDao<?> service){

        System.out.println("===>HqlHelper.buildPageBeanForStruts2()");

       

        PageBean pageBean = service.getPageBean(pageNum,this);

        ActionContext.getContext().getValueStack().push(pageBean);

       

        return this;

    }

}

 

 

在ForumAction中“:

//========================================(最终版)==========================================

    // 最终版:

    // 构建查询条件

    new HqlHelper(Topic.class,"t")//

    .addCondition("t.forum=?", forum)//

    .addCondition(viewType==1,"t.type=?", Topic.TYPE_BEST)// 1表示只看精华帖

    .addOrder(orderBy==1,"t.lastUpdateTime", asc)// 1 代表只按最后更新时间排序

    .addOrder(orderBy==2,"t.postTime", asc)// 2 代表只按主题发表时间排序

    .addOrder(orderBy==3,"t.replyCount", asc)// 3 代表只按回复数量排序

    .addOrder(orderBy==0,"(CASE t.type WHEN 2 THEN 2 ELSE 0END)",false)//

    .addOrder(orderBy==0,"t.lastUpdateTime",false)// 0 代表默认排序(所有置顶帖在前面,并按最后更新时间降序排列)

    .buildPageBeanForStruts2(pageNum, replyService);

   

return "show";