Mybatis使用之分页

一:简介

注:示例基于mysql数据库。Oracle可以自行测试。

 

使用Mybatis分页主要有两种方式、一种是将分页参数传递到配置文件中、在写sql的时候就做分页。另一种是使用Mybatis的拦截器拦截需要分页的sql语句、重新组装成具有分页功能的sql语句。

分页查询的关键在于查询时需要告诉数据库从第几条开始取、取多少条记录。也就是常用到Page对象(一般是方便传递参数、自己构建的实体类)的pageNumer、pageSize两个主要参数。至于Page对象的总记录数等是需要带到前台构造数据展示表格时使用的参数。

二:传递参数形式的分页

2.1 关键点

传递参数形式的分页就是将分页信息以参数的形式传递到映射文件中、这样就可以在编写具体的sql语句时实现分页功能。这种方式的重点在于一般的查询语句都会带有一个或者多个查询参数、而'select'标签的parameterType只能接收一个值。所以需要我们将查询参数与分页参数组装成一个Map作为参数传递到映射语句中。

不过前台展示所需要的数据总数还需要另写一条count查询语句来获取。多多少少会有些不便。

2.2 具体代码

映射文件:

   <select id="selectAuthorWithPageParam"resultType="author" parameterType="hashMap">SELECTt.id,t.username,t.password,t.email,t.bio,t.favourite_section favouriteSectionFROM author tWHERE t.username = {username} AND t.password = {password} limit {page.dbIndex},{page.dbNumber}</select>

映射接口:

   List<Author> selectAuthorWithPageParam(Map<String, Object>map);

测试代码:

   @Testpublic void testSelectAuthorWithPageParam() throws Exception {Page page = new Page();page.count();Map<String, Object> map = new HashMap<>();map.put("page", page);map.put("username", "alien");map.put("password","alien");List<Author> authors =this.authorMapper.selectAuthorWithPageParam(map);Assert.assertEquals(5, authors.size());}

三:拦截器分页

3.1 关键点

拦截器实现分页的关键之处在于、在需要分页的sql语句执行之前、拦截下来并改造成具有分页功能的sql语句(还可以查询一下总数、设置到Page实体类中供前台展示数据时使用)、然后继续执行。

3.2 具体代码

说起来很简单、但是短短的一句话却需要理解许多东西才能达到目的。这里只挑一些重点步骤、具体拦截器工作原理、执行过程会在Mybatis深入过程详细分析。

从使用角度来考虑过程如下(***对所有映射语句id以‘ByPage'结尾的做分页处理***):

3.2.1 Page实体类:

package org.alien.mybatis.samples.entity;/***Created by andy on 5/25/2015.<br>*Version 1.0-SNAPSHOT<br>*/@SuppressWarnings("unused")public class Page {/*** 总条数*/private int totalNumber;/*** 当前第几页*/private int currentPage;/*** 总页数*/private int totalPage;/*** 每页显示条数*/private int pageNumber = 5;/*** 数据库中limit的参数,从第几条开始取*/private int dbIndex;/*** 数据库中limit的参数,一共取多少条*/private int dbNumber;/*** Oracle 起始记录行号*/private int rowNum;/*** Oracle 结束记录行号*/private int rn;/*** 根据当前对象中属性值计算并设置相关属性值*/public void count() {// 计算总页数int totalPageTemp = this.totalNumber / this.pageNumber;int plus = (this.totalNumber % this.pageNumber) == 0 ? 0 : 1;totalPageTemp = totalPageTemp + plus;if(totalPageTemp <= 0) {totalPageTemp = 1;}this.totalPage = totalPageTemp;// 设置当前页数// 总页数小于当前页数,应将当前页数设置为总页数if(this.totalPage < this.currentPage) {this.currentPage = this.totalPage;}// 当前页数小于1设置为1if(this.currentPage < 1) {this.currentPage = 1;}// 设置limit的参数this.dbIndex = (this.currentPage - 1) * this.pageNumber;this.dbNumber = this.pageNumber;}public int getTotalNumber() {return totalNumber;}public void setTotalNumber(int totalNumber) {this.totalNumber = totalNumber;this.count();}public int getCurrentPage() {return currentPage;}public void setCurrentPage(int currentPage) {this.currentPage = currentPage;}public int getTotalPage() {return totalPage;}public void setTotalPage(int totalPage) {this.totalPage = totalPage;}public int getPageNumber() {return pageNumber;}public void setPageNumber(int pageNumber) {this.pageNumber = pageNumber;this.count();}public int getDbIndex() {return dbIndex;}public void setDbIndex(int dbIndex) {this.dbIndex = dbIndex;}public int getDbNumber() {return dbNumber;}public void setDbNumber(int dbNumber) {this.dbNumber = dbNumber;}public int getRn() {return (this.getCurrentPage() + 1) * this.getPageNumber();}public void setRn(int rn) {this.rn = rn;}public int getRowNum() {return this.getCurrentPage() * this.getPageNumber();}public void setRowNum(int rowNum) {this.rowNum = rowNum;}

3.2.2 拦截器类:

packageorg.alien.mybatis.samples.interceptor;importorg.alien.mybatis.samples.entity.Page;importorg.apache.ibatis.executor.parameter.ParameterHandler;importorg.apache.ibatis.executor.statement.StatementHandler;import org.apache.ibatis.mapping.BoundSql;importorg.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.*;importorg.apache.ibatis.reflection.MetaObject;importorg.apache.ibatis.reflection.SystemMetaObject;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.util.Map;import java.util.Properties;/***Page interceptor.*Support oracle and mysql.*Created by andy on 5/25/2015.<br>*Version 1.0-SNAPSHOT<br>*/@Intercepts({@Signature(type =StatementHandler.class, method = "prepare", args ={Connection.class})})public class PageInterceptor implementsInterceptor {private String dialect;@Overridepublic Object intercept(Invocation invocation) throws Throwable {StatementHandler statementHandler =(StatementHandler) invocation.getTarget();MetaObject metaObject = MetaObject.forObject(statementHandler,SystemMetaObject.DEFAULT_OBJECT_FACTORY,SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY);MappedStatement mappedStatement = (MappedStatement)metaObject.getValue("delegate.mappedStatement");String sqlId = mappedStatement.getId();//intercept select sql witch end with "ByPage".if (sqlId.matches(".+ByPage$")) {BoundSql boundSql = (BoundSql)metaObject.getValue("delegate.boundSql");String sql = boundSql.getSql();ParameterHandler parameterHandler = (ParameterHandler)metaObject.getValue("delegate.parameterHandler");Map<?, ?> paramMap = (Map<?, ?>)parameterHandler.getParameterObject();Page page = (Page) paramMap.get("page");//set countConnection connection = (Connection) invocation.getArgs()[0];String countSql = "select count(1) from (" + sql + ")a";PreparedStatement preparedStatement =connection.prepareStatement(countSql);parameterHandler.setParameters(preparedStatement);ResultSet resultSet = preparedStatement.executeQuery();if (resultSet.next()) {page.setTotalNumber(resultSet.getInt(1));}//construct record limit sql by dialectString pageSql;if ("oracle".equals(dialect.toLowerCase())) {pageSql = "select * from" +"(select a.*,rownum rn from (" + sql + ") a where rownum >= " +page.getRowNum() + ") " +"rn < " +page.getRn();} else if ("mysql".equals(dialect.toLowerCase())) {pageSql = sql + " limit" + page.getDbIndex() + "," + page.getDbNumber();} else {pageSql = sql;}metaObject.setValue("delegate.boundSql.sql", pageSql);}return invocation.proceed();}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {this.dialect = properties.getProperty("dialect");}
}

3.2.3 mybatis.xml总配置文件中注册拦截器

***注意Mybatis配置文件各个元素的顺序!***          

   <plugins><plugin interceptor="org.alien.mybatis.samples.interceptor.PageInterceptor"><!--database dialect, only support mysql and oracle--><property name="dialect" value="mysql"/></plugin></plugins>

3.2.4 映射文件语句

   <select id="selectAuthorByPage" resultType="author"parameterType="hashMap">SELECTt.id,t.username,t.password,t.email,t.bio,t.favourite_section favouriteSectionFROM author tWHERE t.username = {username} AND t.password = {password}</select>

3.2.4 映射接口方法

   List<Author> selectAuthorByPage(Map<String, Object> map);

3.2.4 测试方法

   @Testpublic void testSelectAuthorByPage() throws Exception {Page page = new Page();Map<String, Object> map = new HashMap<>();map.put("page", page);List<Author> authors = this.authorMapper.selectAuthorByPage(map);Assert.assertEquals(5, authors.size());}

三:补充

更多内容:Mybatis 目录

篇幅有限、仅仅说明了拦截器的实现过程、原理及代码都没有详细说明、这些会在Mybatis深入中详细解析。

Mybatis使用之分页相关推荐

  1. Mybatis自定义轻量级分页组件(易集成,易拓展)

    Mybatis自定义轻量级分页组件(易集成,易拓展) 其实github有一个叫做PageHelper的开源分页组件,我也用过,封装的还可以.只是感觉他的量级偏重,其实很多参数,都是我们开发中不需要的参 ...

  2. Mybatis最入门---分页查询(逻辑分页与SQL语句分页)

    [一步是咫尺,一步即天涯] 到目前为止,我们介绍的Mybatis种种查询都是一次性的查询出所有结果并返回给上层.但是,在实际开发过程中,在大量数据存在的情况下,是很少这么做的.本文,我们将从逻辑分页, ...

  3. Mybatis如何实现分页

    Mybatis如何实现分页 关键字limit实现分页 Interceptor Plugin实现分页 首先定一个拦截器,拦截器会拦截所有以ByPage结尾的方法,然后拼接sql 语句的limit关键字实 ...

  4. 【Mybatis】mybatis如何实现分页

    [Mybatis]mybatis如何实现分页 mysql分页功能原理 实现分页必要条件 必须知道某一页从哪里开始到哪里结束 必须知道页面的大小,也就是指定每页要显示多少条数据量 mysql分页的过程 ...

  5. Mybatis如何进行分页的

    Mybatis如何进行分页的 Mybatis是Java应用开发的基础框架,而分页是我们时时都在使用的功能,一般我们可以把分页分为两种: 逻辑分页.先查询出所有的数据缓存到内存里,再根据业务相关的一些需 ...

  6. 前端Vue+ElementUI的Pagination分页组件实现分页展示 后端Spring Boot +Mybatis Plus实现分页接口

    前端Vue+ElementUI的Pagination分页组件实现分页展示 & 后端Spring Boot +Mybatis Plus实现分页接口 很久没有更新博客了,主要原因是博主一直在补充自 ...

  7. 一步步教你mybatis分页,mybatis分页拦截器 使用,mybatis拦截器分页

              mybatis 分页详解.mybatis分页查询,mybatis分页拦截器使用.struts2下mybatis分页 mybatis默认是支持分页的,内部通过创建可滚动的Result ...

  8. MyBatis插件使用--分页插件与性能拦截器

    对于PageHelper网上的资料很多,作者的文档写的很全面,我这里只是记录自己的配置和使用的方法 所需jar包:jsqlparser-0.9.5.jar和pagehelper-5.0.0.jar X ...

  9. Mybatis3.3.x技术内幕(十三):Mybatis之RowBounds分页原理

    2019独角兽企业重金招聘Python工程师标准>>> Mybatis可以通过传递RowBounds对象,来进行数据库数据的分页操作,然而遗憾的是,该分页操作是对ResultSet结 ...

最新文章

  1. Objective C 错误整理
  2. 湖南网络推广浅析外链怎么发才会更快的收录?
  3. NYOJ 17 单调递增最长公共子序列
  4. 用DELPHI的RTTI实现对象的XML持久化 【转】
  5. Scala集合List的常用方法:take/flatMap/filter/zip/union/intersect/diff及WordCount集合实现
  6. Activity生命周期的学习和验证
  7. TexBox.AutoCompleteSource
  8. 【javascript】操作符:一元操作符
  9. 雷林鹏分享:PHP 数组排序
  10. excel打印二维码
  11. VS code + miktex + 内置pdf阅读器 配置latex编译环境
  12. Digital Photo Professional 4 如何导出jpg
  13. pagehelper circular references
  14. vb.net 实现图片圆形渐变模糊
  15. 微信帐号检测的实用小方法
  16. 海康摄像头音频编码获取
  17. STM32cube 控制 AIP650 TM1650
  18. Plasma: Scalable Autonomous Smart Contracts 翻译
  19. 0904、kali、使用john破解密码、nmap扫描、抓包、安全加固、Linux加固
  20. uva188 完美哈希题解

热门文章

  1. 开源Excel报表工具:jxls
  2. Python:安装 psycopg2
  3. 70道关于JavaScript的常见面试题解答
  4. FHS--文件系统结构
  5. Java-SpringBoot-使用Sigar采集设备信息
  6. Java软件工程师[初级测试题]
  7. Java操作Excel之Excel文件的下载
  8. 什么扫地机器人好用,哪一款扫地机器人好?
  9. docker下载镜像新建容器打包容器打包tar加载tar
  10. 【优化求解】基于matlab禁忌搜索算法求解函数极值问题【含Matlab源码 1204期】