Mybatis使用之分页

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">

       SELECT

           t.id,

           t.username,

           t.password,

           t.email,

           t.bio,

           t.favourite_section favouriteSection

       FROM author t

       WHERE t.username = {username} AND t.password = {password} limit {page.dbIndex},{page.dbNumber}

   </select>

    映射接口:

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

  

    测试代码:

  

   @Test

   public 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设置为1

       if(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;

 

   @Override

   public 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 count

           Connection 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 dialect

           String 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();

    }

 

   @Override

   public Object plugin(Object target) {

       return Plugin.wrap(target, this);

    }

 

   @Override

   public 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">

       SELECT

           t.id,

           t.username,

           t.password,

           t.email,

           t.bio,

           t.favourite_section favouriteSection

       FROM author t

       WHERE t.username = {username} AND t.password = {password}

   </select>


3.2.4 映射接口方法


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

3.2.4 测试方法

   @Test

   public 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深入中详细解析。


  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis 是一个优秀的持久层框架,而 PageHelper 是一个用于 MyBatis分页插件使用 PageHelper 可以方便地实现分页功能。下面是使用 PageHelper 进行分页的步骤: 1. 添加依赖:在项目的 `pom.xml` 文件中添加以下依赖: ```xml <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>latest-version</version> </dependency> ``` 可以在 Maven 仓库中找到最新版本的 PageHelper。 2. 配置 PageHelper:在 MyBatis 的配置文件中添加以下配置项: ```xml <plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!-- 可选:设置数据库方言,用于支持不同数据库的分页 --> <property name="dialect" value="mysql"/> <!-- 可选:设置为 true 启用合理化查询,开启后,如果 pageSize=0 或者 PageMethod 的 `count` 参数为 true,则会查询总数 --> <property name="reasonable" value="true"/> </plugin> </plugins> ``` 注意:根据你所使用的数据库类型,需要将 `dialect` 属性配置为相应的数据库方言。 3. 使用 PageHelper 进行分页:在需要进行分页的查询方法中,使用 PageHelper 的静态方法来设置分页参数,例如: ```java import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; // ... // 设置分页参数,pageNum 表示当前页数,pageSize 表示每页显示的记录数 PageHelper.startPage(pageNum, pageSize); // 执行查询 List<MyEntity> resultList = myEntityMapper.selectByExample(example); // 封装查询结果,并返回给前端 PageInfo<MyEntity> pageInfo = new PageInfo<>(resultList); return pageInfo; ``` 这样就完成了使用 PageHelper 进行分页的配置和使用。PageHelper 会自动在查询语句后面添加分页的 SQL 语句,根据传入的分页参数进行数据查询和结果封装。返回的 `PageInfo` 对象可以用于获取分页相关的信息,如总记录数、总页数等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值