跟着汤阳光同志做一个OA系统(十二):通用的分页实现、HQL生成器QueryHelper

79 篇文章 1 订阅
35 篇文章 0 订阅

======================= 本页的数据列表 ========================

<s:iterator value="recordList">

         ...

</s:iterator>

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

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

每页显示:${pageSize}条  

总记录数:${recordCount}条 

 

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

         ...

</s:iterator>

 

转到:

<selectοnchange="gotoPage(this.value)">

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

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

         </s:iterator>

</select>

 

 

<script>

         function gotoPage(pageNow){

                   window.location.href = "url? pageNow ="+ pageNow;

         }

</script>

 

 

 

 

 

======== 页面中需要显示的数据 ===========

 

recordList                  本页的数据列表

pageNow             当前页

pageCount                 总页数

pageSize              每页显示多少条

recordCount              总记录数

beginPageIndex       页码列表的开始索引

endPageIndex     页码列表的结束索引

 

 

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

 

假设共25条数据,每页显示10条,则共3页

 

                   first  max

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

第1页       0                10

第2页       10              10

第3页       20              10

 

first = (pageNow - 1) *pageSize

max = pageSize

 

 

实现分页的流程

设计一个实体PageBean,这中间就包含分页的所有信息,由service提供,传入需要的参数。

PageBean的设计

publicclass PageBean {

 

    // 指定的或是页面参数

    privateintcurrentPage; // 当前页

    privateintpageSize; // 每页显示多少条

 

    // 查询数据库

    privateintrecordCount; // 总记录数

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

 

    // 计算

    privateintpageCount; // 总页数

    privateintbeginPageIndex; // 页码列表的开始索引(包含)

    privateintendPageIndex; // 页码列表的结束索引(包含)

 

    /**

     * 只接受前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 {

           // 当前页附近的共10个页码(前4 + 当前页 + 5个)

           beginPageIndex = currentPage - 4;

           endPageIndex = currentPage + 5;

           // 当前面的页码不足4个时,则显示前10个页码

           if (beginPageIndex < 1) {

              beginPageIndex = 1;

              endPageIndex = 10;

           }

           // 当后面的页码不足5个时,则显示后10个页码

           if (endPageIndex > pageCount) {

              endPageIndex = pageCount;

              beginPageIndex = pageCount - 10 + 1;

           }

       }

    }

。。。

}

 

 

实现第一个分页(回复贴分页)

Action中

 

来源于页面

privateintpageNum = 1;//当前页,默认第一页

 

    privateintpageSize = 10;//每页数量,默认10

 

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

    public String show() throws Exception {

       // 准备数据:topic

       Topic topic = topicService.getById(model.getId());

       ActionContext.getContext().put("topic", topic);

      

//     // 准备数据:replyList

//     List<Reply> replyList = replyService.findByTopic(topic);

//     ActionContext.getContext().put("replyList",replyList);

      

      

       // // 准备分页信息 v1

       PageBean pageBean = replyService.getPageBeanByTopic(pageNum, pageSize, topic);

       ActionContext.getContext().getValueStack().push(pageBean);//放在栈顶就能少写一些#对象

      

       topicId = model.getId();

      

       return"show";

    }

 

 

Service的实现中

public PageBean getPageBeanByTopic(int pageNum, int pageSize, Topic topic) {

 

       // 查询本页的数据列表

       List list = getSession().createQuery(//

              "FROM Replyr WHERE r.topic=? ORDER BY r.postTime ASC")//

              .setParameter(0, topic)//

              .setFirstResult((pageNum - 1) * pageSize)//

              .setMaxResults(pageSize)//

              .list();

 

       // 查询总记录数量

       Long count = (Long) getSession().createQuery(//

              "SELECTCOUNT(*) FROM Reply r WHERE r.topic=?")//

              .setParameter(0, topic)//

              .uniqueResult();

 

       returnnew PageBean(pageNum, pageSize, count.intValue(), list);

    }

 

 

JSP

前面方然按照自己的循环显示所有的列表数据

       <!--分页信息-->

       <div id=PageSelectorBar>

           <div id=PageSelectorMemo>

              页次:${currentPage}/${pageCount }&nbsp;

              每页显示:${pageSize }&nbsp;

              总记录数:${recordCount }

           </div>

           <div id=PageSelectorSelectorArea>

          

              <a href="javascript: gotoPage(1)" title="首页" style="cursor: hand;">

                  <img src="${pageContext.request.contextPath}/style/blue/images/pageSelector/firstPage.png"/>

              </a>

             

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

                  <s:if test="#num ==currentPage"><%-- 当前页 --%>

                     <span class="PageSelectorNumPageSelectorSelected">${num}</span>

                  </s:if>

                  <s:else><%-- 非当前页 --%>

                     <span class="PageSelectorNum"style="cursor: hand;" onClick="gotoPage(${num});">${num}</span>

                  </s:else>

                 

              </s:iterator>

             

              <a href="javascript: gotoPage(${pageCount})" title="尾页" style="cursor: hand;">

                  <img src="${pageContext.request.contextPath}/style/blue/images/pageSelector/lastPage.png"/>

              </a>

             

              转到:

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

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

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

                  </s:iterator>

              </select>

              <!-- 回显 -->

              <script type="text/javascript">

                  $("#_pn").val("${currentPage}");

              </script>

             

           </div>

       </div>

      

      

       <script type="text/javascript">

           function gotoPage( pageNum ){

              window.location.href = "topic_show.action?id=${id}&pageNum=" + pageNum;

           }

       </script>

 

为了减少代码和以后带过滤参数,我们把上面script替换为

<scripttype="text/javascript">

         function gotoPage( pageNum ){

                   // window.location.href = "forum_show.action?id=${id}&pageNum="+ pageNum;

                  

                   $(document.forms[0]).append("<inputtype='hidden' name='pageNum' value='" + pageNum +"'>");

                   document.forms[0].submit();

         }

</script>

 

而在分页的地方,因为form天生就能带参数,所以排序和过滤的条件就可以放在这个form中,但是保证这个form在这个页面中是第一个

 

 

增加过滤条件

<div id="TableTail">

              <div id="TableTail_inside">

                  <table border="0"cellspacing="0" cellpadding="0"height="100%" align="left">

                     <tr valign=bottom>

                         <td></td>

                         <td>

                           

                            <s:select name="viewType"list="#{0:'全部主题', 1:'全部精华贴'}"/>

 

                            <s:select name="orderBy"onchange="onSortByChange(this.value)"

                                list="#{0:'默认排序(所有置顶帖在前面,并按最后更新时间降序排列)', 1:'只按最后更新时间排序', 2:'只按主题发表时间排序', 3:'只按回复数量排序'}"                            

                            />

                           

                            <s:select name="asc"list="#{false:'降序', true:'升序'}"/>

                           

                            <input type="IMAGE"src="${pageContext.request.contextPath}/style/blue/images/button/submit.PNG" align="ABSMIDDLE"/>

                         </td>

                     </tr>

                  </table>

              </div>

           </div>

 

 

Service的分页合并后提取到DaoSupport

// 公共的查询分页信息的方法

    public PageBean getPageBean(int pageNum, int pageSize, String hql, List<Object>parameters) {

//     System.out.println("------->DaoSupportImpl.getPageBean()");

 

       // 查询本页的数据列表

       Query listQuery = getSession().createQuery(hql); // 创建查询对象

       if (parameters != null) { // 设置参数

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

              listQuery.setParameter(i, parameters.get(i));

           }

       }

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

       listQuery.setMaxResults(pageSize);

       List list = listQuery.list(); // 执行查询

 

       // 查询总记录数量

       Query countQuery = getSession().createQuery("SELECT COUNT(*) " + hql);

       if (parameters != null) { // 设置参数

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

              countQuery.setParameter(i, parameters.get(i));

           }

       }

       Long count = (Long) countQuery.uniqueResult(); // 执行查询

 

       returnnew PageBean(pageNum, pageSize, count.intValue(), list);

    }

 

 

QueryHelper来帮助生成HQL语句

/**

 *

 * 调用方式】

 * QueryHelper helper = newQueryHelper(Reply.class, "r")//

                            .addCondition("r.topic=?",topic)//

                            .addOrderProperty("r.postTime",true);

      

       PageBean pageBean = replyService.getPageBean(pageNum,pageSize, helper);

       或者添加conditionorderby之后直接调用preparePageBean

 */

/**

 *

 * FROM       必须

       实体名

   WHERE       可选

      条件1 AND 条件2 AND ... 条件n

   ORDER BY    可选

     属性1, 属性2, ... 属性n

 * 用于辅助拼接HQL语句

 *

 *

 * 支持方法连缀

 * 生成HQL语句

 * 生成参数列表

 * 生成查询总记录数的HQL,去除掉OrderBy

 * 直接生成PageBean

 * @author tyg

 * StringBuffer代替String应该还能提升性能

 */

publicclass QueryHelper {

 

    private StringBuffer fromClause; // FROM子句

    private StringBuffer whereClause = new StringBuffer(""); // Where子句

    private StringBuffer orderByClause = new StringBuffer(""); // OrderBy子句

 

    private List<Object> parameters = new ArrayList<Object>(); // 参数列表

 

    /**

     * 生成From子句

     *

     * @param clazz

     * @param alias

     *            别名

     *            FROM Topic t

     */

    public QueryHelper(Class clazz, String alias) {

       fromClausenew StringBuffer("FROM ")

                         .append(clazz.getSimpleName())

                         .append(" ")

                         .append(alias);

    }

 

    /**

     * 拼接Where子句

     *  d.id BETWEEN ? AND ?

        d.parent=?

        d.parent IS NULL

     * @param condition

     * @param params

     */

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

       // 拼接

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

           whereClausenew StringBuffer(" WHERE ").append(condition);

       } else {

           whereClause.append(" AND ").append(condition);

       }

 

       // 参数

       if (params != null) {

           for (Object p : params) {

              parameters.add(p);

           }

       }

 

       returnthis;

    }

 

    /**

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

     *

     * @param append

     * @param condition

     * @param params

     */

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

       if (append) {

           addCondition(condition, params);

       }

       returnthis;

    }

 

    /**

     * 拼接OrderBy子句

     *

     * @param propertyName

     *            参与排序的属性名

     * @param asc

     *            true表示升序,false表示降序

     */

    public QueryHelper addOrderProperty(String propertyName, boolean asc) {

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

           orderByClausenew StringBuffer(" ORDER BY ").append(propertyName + (asc ? "ASC" : "DESC"));

       } else {

           orderByClause.append(", ").append(propertyName + (asc ? " ASC" : " DESC"));

       }

       returnthis;

    }

 

    /**

     * 如果第一个参数为true,则拼接OrderBy子句

     *

     * @param append

     * @param propertyName

     * @param asc

     */

    public QueryHelper addOrderProperty(boolean append, String propertyName, boolean asc) {

       if (append) {

           addOrderProperty(propertyName, asc);

       }

       returnthis;

    }

 

    /**

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

     *

     * @return

     */

    public String getListQueryHql() {

       returnnew StringBuffer(fromClause).append(whereClause).append(orderByClause).toString();

    }

 

    /**

     * 获取生成的用于查询总记录数的HQL语句

     *

     * @return

     */

    public String getCountQueryHql() {

       return"SELECTCOUNT(*) " + fromClause + whereClause;

    }

 

    /**

     * 获取HQL中的参数值列表

     *

     * @return

     */

    public List<Object> getParameters() {

       returnparameters;

    }

 

    /**

     * 查询分页信息,并放到值栈栈顶

     *

     * @param service

     * @param pageNum

     * @param pageSize

     */

    publicvoid preparePageBean(DaoSupport<?> service, int pageNum, int pageSize) {

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

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

    }

 

}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值