MyBatis实现拦截器分页功能

本文介绍了如何利用MyBatis的拦截器实现分页功能。首先讲解了拦截器的工作原理,包括修改SQL以获取记录总数,然后通过拼接`LIMIT`或`ROWNUM`实现分页。接着,详细说明了实现步骤,包括创建PageBean,配置拦截器,以及在JSP界面展示分页。最后,提供了相关代码示例,包括PageBean、拦截器Interceptor的实现和JSP界面的分页控制。
摘要由CSDN通过智能技术生成

MyBatis实现拦截器分页功能

1.原理

  • 在mybatis使用拦截器(interceptor),截获所执行方法的sql语句与参数。
    (1)修改sql的查询结果:将原sql改为查询count(*) 也就是条数
    (2)将语句sql进行拼接 limit(MySql)或rownum(Oracle)语句达到分页效果
  • 制作分页Page类,需要分页的bean继承分页Page类。
  • jsp界面通过Page类的属性参数实现对页数控制。

2.具体步骤

(1)首先创建PageBean
(2)配置分页使用的拦截器实现Interceptor接口,重写其抽象方法

@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }),
        @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = { Statement.class }) })
public class PageInterceptor implements Interceptor {
      
@Intercepts注解表示被会被拦截的类和方法参数
//SELECT_ID 根据被捕获的方法判断是否需要进行分页 如果方法名含有Page则进行分页
private static final String SELECT_ID = "Page";
//在intercept方法中获取mybatis.xml中的property属性值为PageCount赋值
private Properties properties;
//通过PageBean对象获取Count值的where条件后参数
private PageBean pageBean;

1. 拦截器的主方法则是具体功能的实现,主要做的事:

  • 判断被拦截的方法是否需要进行分页

  • 需要分页则截取sql语句,截取条件并拼接成查询条数,也就是将

    select * from user    ---->  select count(*) from user
  • 获取数据库连接对象,并执行拼接好的count(*)获取条数Sql语句获取数据库条数 ,并将值存到设计好的PageBean对象中
//获取数据库连接对象
Connection connection = (Connection) invocation.getArgs()[0];
//执行countSql语句 并获得Count值 为PageBean的totalCount赋值
PreparedStatement countStmt = null;
ResultSet rs = null;
int totalCount = 0;
try {
countStmt = connection.prepareStatement(countSql);
    rs = countStmt.executeQuery();
if (rs.next()) {
    totalCount = rs.getInt(1);
}
} catch (SQLException e) {
    System.out.println("Ignore this exception" + e);
} finally {
try {
    rs.close();
    countStmt.close();
} catch (SQLException e) {
    System.out.println("Ignore this exception" + e);
    }
}
  • 将原sql语句增加limit a,b a为查询结果第一条,b为所查询的条数
public String concatPageSql(String sql, PageBean pageBean) {
        StringBuffer sb = new StringBuffer();
        sb.append(sql);
        sb.append(" limit ").append(pageBean.getPageLimit()).append(" ,").append(pageBean.getPageCount());
        return sb.toString();
    }
  • 将拦截修改好的sql语句传递给dao层执行的方法 并返回对应的结果

//将处理好的SQL语句绑定
String pageSql = concatPageSql(sql, pageBean);
//将修改好的sql语句返回给方法
metaStatementHandler.setValue("delegate.boundSql.sql", pageSql);
  • 退出拦截器,开始执行dao层方法,执行sql语句进行数据处理
//执行dao层方法
return invocation.proceed();

Controller中配置 接收参数与返回参数

  • 参数为PageBean的子类对象–接收由JSP中传入的分页数据信息–模糊查询的参数等等
  • 而参数在dao层方法完成后,会在拦截器中对其分页数据进行赋值–也就是经过拦截器处理后,对象的数据增加了
  • 以User类为例
@RequestMapping("/selectLikeUser.do")
    //参数为user 而mav.addObject("pageBean", user); 也是user,这是拦截器有对user进行分页信息赋值
    public ModelAndView selectPageLikeAllUser(User user){
        //执行的顺序Service-->拦截器(修改sql语句,注入分页参数)-->Dao方法-->返回结果
        //所以有两个值 ① 分页的数据(当前页,总页数等数据)在user对象中
        //           ② 保存数据的集合userList
        List<User> userList=this.userService.selectPageLikeAllUser(user);
        ModelAndView mav=new ModelAndView();
        mav.addObject("userList", userList);
        //对应的前台Jsp界面
        mav.setViewName("userList");
        //将分页数据保存
        mav.addObject("pageBean", user);
        return mav;
    }

前台Jsp界面
- 翻页需要的button模块

<div class="div_input">
    //分页需要用到的参数有JS对应的方法进行表单提交时传递参数 而limtr 从0开始,后台执行sql语句 limit 0,每页的条数
    //每次点击下一页 变化的都是limit 前面的参数 limit 参数*条数,条数
    //第一页 limit 0*2,2
    //第二页 limit 1*2,2
    //第三页 limit 2*2,2 …………
    <input type="button" class="input_scan" value="首页" onclick="page(0)"/> 
    //判断上一页的方法,当表单无上一页是 当前input会被隐藏
    <c:if test="${pageBean.previous}">
        <input type="button" class="input_scan" value="上页" onclick="page(${pageBean.pageNo - 1})"/> 
    </c:if>
    //判断下一页的方法,当前为最大页时,input隐藏
    <c:if test="${pageBean.next}">
        <input type="button" class="input_scan" value="下页" onclick="nextPage(${pageBean.pageNo + 1},${pageBean.totalPage})"/>
    </c:if>
    <input type="button" class="input_scan" value="末页" onclick="page(${pageBean.totalPage -1})"/> 
    <span class="span_text">跳到第</span>
        <input type="text" class="input_text" name="pageNo" id="pageID"/>
    <span class="span_text">页</span> 
        <input type="button" class="input_scan" value="跳转" onclick="pageSubmit(${pageBean.totalPage})"/>
</div>
  • 对应的JS方法
//每一次表单的提交,在controller中捕获的都是pageID的那个type='text'的那个文本框
//方法中的逻辑判断则是为了避免一些提交bug,保证pageID的文本框中数值显示正常以及跳转按钮等等
<script type="text/javascript">
function page(pageArg){
       
    var myform = document.getElementById("myform");
    var pageNo = document.getElementById("pageID");
    pageNo.value = pageArg;
    if(pageArg!=-1){
        myform.submit();
    }else{
        pageNo.value ="";
    }

}
function pageSubmit(pageArg){
       
    var myform = document.getElementById("myform");
    var pageNo = document.getElementById("pageID");
    if(pageNo.value-1 < pageArg){
        pageNo.value=Number(pageNo.value)-1;
        if(pageNo.value>-1){
            myform.submit();
        }else{
            pageNo.value="";
        }
    }
}
function nextPage(pageArg,totalPage){
       
    var myform = document.getElementById("myform");
    var pageNo = document.getElementById("pageID");
    pageNo.value = pageArg;
    if(pageArg<totalPage)
        myform.submit();
}
</script>

**

下面为完整代码

**

  • 拦截器中,因为模糊查询,所以多了一些判断参数的方法,以及为sql语句的参数赋值的过程,仅供参考

  • PageBean为对应的分页model类,而selectInfo为模糊查询参数,在拦截器中会使用此参数在查询count条数时,修改参数

    **

PageBean

**

package com.chinasofti.lexian.bean;

import java.util.HashMap;

public class PageBean {
      

    private int totalCount;//总的条数

    private int pageNo;//当前的页数

    private int pageCount;//每页的条数

    private int pageLimit;//下一页的条件 等于pageNo*pageCount

    private String storename;
    private String starttime;
    private String closetime;

    private String selectInfo;

    private int state;

    private static HashMap<String, String> infoHashMap;//模糊查询配置参数

    static{
        infoHashMap = new HashMap<String, String>();
    }

    //无参构造方法
    public PageBean() {
        super();
        // TODO Auto-generated constructor stub
    }

    //全参构造方法
    public PageBean(int totalCount, int pageNo, int pageCount) {
        this.totalCount = totalCount;
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值