Java使用MyBatis框架分页的5种方式

本文为大家分享了Java使用MyBatis框架分页的五种方式,供大家参考,具体内容如下

初始准备

1.创建分页对象类,方便模块间传值

//PageInfo.java
import lombok.Data;

@Data
public class PageInfo {

  private int pageNo;

  private int pageSize;

}

2.定义DAO层接口

import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface UserMapper {

  User selectByUser(User user);
  List<User> selectAll();
  List<User> selectByPageInfo(PageInfo info);
  List<User> selectByInterceptor(PageInfo info);

  List<User> selectByRowBounds(RowBounds rowBounds);

}

3.mapper中定义结果集合BaseResult

<resultMap id="BaseResult" type="cn.edu.yau.pojo.User">
    <id property="id" column="id" jdbcType="INTEGER"></id>
    <result property="username" column="username" jdbcType="VARCHAR"></result>
    <result property="password" column="password" jdbcType="VARCHAR"></result>
 </resultMap>

一、原始切分:最原始方法,不建议使用

1.mapper代码:查询所有数据

<select id="selectAll" resultMap="BaseResult">
  select * from tb_user
</select>

2.业务层代码:利用List的subList()方法对数据进行切片

public List<User> findByAll(PageInfo info) {
    List<User> users = userMapper.selectAll();
    return users.subList(info.getPageNo(), info.getPageSize());
  }

3.控制层代码

@RequestMapping(value = "/userlist_1", method = RequestMethod.GET)
@ResponseBody
  public Result findUserBySubList(PageInfo info) {
    List<User> users = userService.findByAll(info);
    if(users.size() == 0) {
      return ResultGenerator.genFailResult("未查找到用户");
    }
    return ResultGenerator.genSuccessResult(users);
  }

二、LIMIT关键字

1.mapper代码:利用limit关键字实现分页

<select id="selectByPageInfo" resultMap="BaseResult">
    select * from tb_user limit #{pageNo}, #{pageSize}
</select>

2.业务层直接调用

public List<User> findByPageInfo(PageInfo info) {
    return userMapper.selectByPageInfo(info);
  }

3.控制层直接调用

三、RowBounds实现分页

1.在DAO层定义好所要传输的分页信息,类型为RowBounds

2.mapper层:查询所有数据

3.业务层:将PageInfo信息封装成RowBounds,调用DAO层方法

public List<User> findByRowBounds(PageInfo info) {
    return userMapper.selectByRowBounds(new RowBounds(info.getPageNo(), info.getPageSize()));
  }

4.控制层直接调用

四、MyBatis的Interceptor实现:实现复杂,需要明白MyBatis的实现

1.创建Interceptor

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.sql.Connection;
import java.util.Properties;

/**
 * 利用MyBatis拦截器进行分页
 *
 * @Intercepts 说明是一个拦截器
 * @Signature 拦截器的签名
 * type 拦截的类型 四大对象之一( Executor,ResultSetHandler,ParameterHandler,StatementHandler)
 * method 拦截的方法
 * args 参数,高版本需要加个Integer.class参数,不然会报错
 *
 */
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class DefinedPageInterceptor implements Interceptor {

  @Override
  public Object intercept(Invocation invocation) throws Throwable {
    //获取StatementHandler,默认的是RoutingStatementHandler
    StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
    //获取StatementHandler的包装类
    MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
    //分隔代理对象
    while (metaObject.hasGetter("h")) {
      Object obj = metaObject.getValue("h");
      metaObject = SystemMetaObject.forObject(obj);
    }
    while (metaObject.hasGetter("target")) {
      Object obj = metaObject.getValue("target");
      metaObject = SystemMetaObject.forObject(obj);
    }
    //获取查看接口映射的相关信息
    MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
    String mapId = mappedStatement.getId();
    //拦截以ByInterceptor结尾的请求,统一实现分页
    if (mapId.matches(".+ByInterceptor$")) {
      System.out.println("LOG:已触发分页拦截器");
      //获取进行数据库操作时管理参数的Handler
      ParameterHandler parameterHandler = (ParameterHandler) metaObject.getValue("delegate.parameterHandler");
      //获取请求时的参数
      PageInfo info = (PageInfo) parameterHandler.getParameterObject();
      //获取原始SQL语句
      String originalSql = (String) metaObject.getValue("delegate.boundSql.sql");
      //构建分页功能的SQL语句
      String sql = originalSql.trim() + " limit " + info.getPageNo() + ", " + info.getPageSize();
      metaObject.setValue("delegate.boundSql.sql", sql);
    }
    //调用原对象方法,进入责任链下一级
    return invocation.proceed();
  }

  @Override
  public Object plugin(Object target) {
    //生成Object对象的动态代理对象
    return Plugin.wrap(target, this);
  }

  @Override
  public void setProperties(Properties properties) {
    //如果分页每页数量是统一的,可以在这里进行统一配置,也就无需再传入PageInfo信息了
  }
}

2.将Interceptor添加至MyBatisConfig中,这里采用JavaConfig的方式

@Bean
  public SqlSessionFactoryBean sqlSession() {
    SqlSessionFactoryBean sqlSession = new SqlSessionFactoryBean();
    sqlSession.setDataSource(dataSource());
    try {
      Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml");
      sqlSession.setMapperLocations(resources);
      //配置自定义的Interceptro作为MyBatis的Interceptor,完成分页操作
      DefinedPageInterceptor definedPageInterceptor = new DefinedPageInterceptor();
      sqlSession.setPlugins(new Interceptor[]{definedPageInterceptor});
      return sqlSession;
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }

3.DAO层接口方法名需要和代码中自定义的".+ByInterceptor$"正则表达式相匹配,mapper的书写依然是查询所有数据

<select id="selectByInterceptor" resultMap="BaseResult">
    select * from tb_user
</select>

4.业务层直接调用

5.控制层直接调用

五、开源项目PageHelper实现:本质还是自己封装了个Interceptor

1.引入PageHelper的jar包

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.10</version>
</dependency>

2.配置PageInterceptor

public PageInterceptor initPageInterceptor(){
    PageInterceptor pageInterceptor = new PageInterceptor();
    Properties properties = new Properties();
    //设置数据库类型
    properties.setProperty("helperDialect", "mysql");
    //该参数默认为false
    //设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用
    //和startPage中的pageNum效果一样
    properties.setProperty("offsetAsPageNum", "true");
    //该参数默认为false
    //设置为true时,使用RowBounds分页会进行count查询
    properties.setProperty("rowBoundsWithCount", "true");
    pageInterceptor.setProperties(properties);
    return pageInterceptor;
  }

  @Bean
  public SqlSessionFactoryBean sqlSession() {
    SqlSessionFactoryBean sqlSession = new SqlSessionFactoryBean();
    sqlSession.setDataSource(dataSource());
    try {
      Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml");
      sqlSession.setMapperLocations(resources);
      //配置PageHelper作为MyBatis的Interceptor,完成分页操作
      PageInterceptor pageInterceptor = this.initPageInterceptor();
      //配置自定义的Interceptro作为MyBatis的Interceptor,完成分页操作
      DefinedPageInterceptor definedPageInterceptor = new DefinedPageInterceptor();
      sqlSession.setPlugins(new Interceptor[]{pageInterceptor, definedPageInterceptor});
      return sqlSession;
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }

3.mapper依然是查询所有数据

4.为DAO层再封装一次方法

@Repository
public class PageHelperHandler {

  @Autowired
  private SqlSessionFactory sqlSessionFactory;

  public List<User> findByPageHelper(PageInfo info) {
    SqlSession session = sqlSessionFactory.openSession();
    PageHelper.startPage(info.getPageNo(), info.getPageSize());
    //写到要使用到的类名和方法名
    List<User> users = session.selectList("cn.edu.yau.mapper.UserMapper.selectAll");
    return users;
  }

}

6.业务层直接调用Handler

7.控制层直接调用

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

时间: 2019-08-22

Java的MyBatis框架中实现多表连接查询和查询结果分页

实现多表联合查询 还是在david.mybatis.model包下面新建一个Website类,用来持久化数据之用,重写下相应toString()方法,方便测试程序之用. package david.mybatis.model; import java.text.SimpleDateFormat; import java.util.Date; public class Website { private int id; private String name; private int visito

Java简单实现SpringMVC+MyBatis分页插件

1.封装分页Page类 package com.framework.common.page.impl; import java.io.Serializable; import com.framework.common.page.IPage; /** * * * */ public abstract class BasePage implements IPage, Serializable { /** * */ private static final long serialVersionUID

Spring Mybatis 分页插件使用教程

Mybatis分页切入点 Mybatis内部有个plugins(插件)概念,本质上属于拦截器的思想.具体的解析可见他文MyBatis拦截器原理探究.本文将在此基础上直接展示实际项目的实现代码和其他的相关解析 分页具体代码实现 首先我们可以定义方言抽象类,用于实现分页AbstractDialect.java public abstract class AbstractDialect{ /** * 是否支持limit和偏移量 * @return */ public abstract boolean

mybatis分页插件pageHelper详解及简单实例

mybatis分页插件pageHelper详解及简单实例 工作的框架spring springmvc mybatis3 首先使用分页插件必须先引入maven依赖,在pom.xml中添加如下 <!-- 分页助手 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>3.7.5

Mybatis分页插件PageHelper的配置和简单使用方法(推荐)

前言 在web开发过程中涉及到表格时,例如dataTable,就会产生分页的需求,通常我们将分页方式分为两种:前端分页和后端分页. 前端分页 一次性请求数据表格中的所有记录(ajax),然后在前端缓存并且计算count和分页逻辑,一般前端组件(例如dataTable)会提供分页动作. 特点是:简单,很适合小规模的web平台:当数据量大的时候会产生性能问题,在查询和网络传输的时间会很长. 后端分页 在ajax请求中指定页码(pageNum)和每页的大小(pageSize),后端查询出当页的数据返回

SSM使用mybatis分页插件pagehepler实现分页示例

前几天在这里分享了手写 sql 分页查询实现分页,现在来看看使用 mybatis 分页插件 pagehepler 来实现分页 使用分页插件的原因,简化了sql代码的写法,实现较好的物理分页,比写一段完整的分页sql代码,也能减少了误差性. Mybatis分页插件 demo 项目地址:free-Mybatis_PageHelper_jb51.rar 我这里使用 maven 工程实现: 1.首先导入分页插件的依赖: <dependency> <groupId>com.github.pa

Mybatis分页插件使用方法详解

本文实例为大家分享了Mybatis分页插件使用的具体代码,供大家参考,具体内容如下 1.分页插件简介 pagehelper源码 都说这是史上最好用的分页插件,支持多种数据库以多种方式分页. 2.分页插件的使用 2.1导入maven依赖 <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>最新

SpringBoot 使用Mybatis分页插件实现详解

这篇文章主要介绍了SpringBoot 使用Mybatis分页插件实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.导入分页插件包和jpa包 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </depende

Mybatis分页插件的实例详解

Mybatis分页插件的实例详解 1.前言: 我们知道,在MySQL中,分页的sql是使用limit来做,如果我们自己写sql,那分页肯定是没有任何问题的.但是一旦model多了起来,复杂了起来,我们很自然的想到使用mybatis的逆向工程来生成相应的po和mapper,但是同时也会带来弊端,比如这里的分页问题就不好解决了. 可能有人会说,我可以修改生成的文件,没错,这是可行的,但是一般我们通过逆向工程生成的文件,都不会去动它,所以这个时候,就需要使用分页插件来解决了. 如果你也在用Mybati

MyBatis分页插件PageHelper的具体使用

MyBatis分页插件PageHelper 如果你也在用 MyBatis,建议尝试该分页插件,这一定是最方便使用的分页插件.分页插件支持任何复杂的单表.多表分页. PageHelper是一个Mybatis的分页插件, 负责将已经写好的sql语句, 进行分页加工. PageHelper的使用 优点:无需你自己去封装以及关心sql分页等问题,使用很方便,前端取数据也很方便. 1.引入pagehelper依赖 <dependency> <groupId>com.github.pagehe

浅谈Mybatis分页插件,自定义分页的坑

场景:PageHelper 的默认分页方案是 select count(0) from (你的sql) table_count 由于查询数据比较大时,导致分页查询效率低下. 优化:使用自定义的count查询.. 废话不多说,对应代码如下: 这个时候会使用自定义的 count sql进行统计查询. 然后一般分页默认使用 PageHelper.startPage(); 作者优化:如果获取的数量大于实际数量,则进行pageNum优化. 所以 最好建议重载 startPage. 不进行优化!!! 要不然