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简单实现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

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的MyBatis框架中XML映射缓存的使用教程

MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制.默认情况下是没有开启缓存的,要开启二级缓存,你需要在你的SQL映射文件中添加一行: <cache/> 字面上看就是这样.这个简单语句的效果如下: 1.映射语句文件中的所有select语句将会被缓存. 2.映射语句文件中的所有insert,update和delete语句会刷新缓存. 3.缓存会使用Least Recently Used(LRU,最近最少使用的)算法来收回. 4.根据时间表(比如 no Flush Inter

Java的MyBatis框架中MyBatis Generator代码生成器的用法

关于Mybatis Generator MyBatis Generator (MBG) 是一个Mybatis的代码生成器 MyBatis 和 iBATIS. 他可以生成Mybatis各个版本的代码,和iBATIS 2.2.0版本以后的代码. 他可以内省数据库的表(或多个表)然后生成可以用来访问(多个)表的基础对象. 这样和数据库表进行交互时不需要创建对象和配置文件. MBG的解决了对数据库操作有最大影响的一些简单的CRUD(插入,查询,更新,删除)操作. 您仍然需要对联合查询和存储过程手写SQL

详解Java的MyBatis框架中动态SQL的基本用法

有些时候,sql语句where条件中,需要一些安全判断,例如按某一条件查询时如果传入的参数是空,此时查询出的结果很可能是空的,也许我们需要参数为空时,是查出全部的信息.使用Oracle的序列.mysql的函数生成Id.这时我们可以使用动态sql.下文均采用mysql语法和函数(例如字符串链接函数CONCAT). selectKey 标签 在insert语句中,在Oracle经常使用序列.在MySQL中使用函数来自动生成插入表的主键,而且需要方法能返回这个生成主键.使用myBatis的select

整理Java的MyBatis框架中一些重要的功能及基本使用示例

基本用法回顾: SQL语句存储在XML文件或Java 注解中.一个MaBatis映射的示例(其中用到了Java接口和MyBatis注解): package org.mybatis.example; public interface BlogMapper { @Select("select * from Blog where id = #{id}") Blog selectBlog(int id); } 执行的示例: BlogMapper mapper = session.getMapp

Java的MyBatis框架中对数据库进行动态SQL查询的教程

其实MyBatis具有的一个强大的特性之一通常是它的动态 SQL 能力. 如果你有使用 JDBC 或其他 相似框架的经验,你就明白要动态的串联 SQL 字符串在一起是十分纠结的,确保不能忘了空格或在列表的最后省略逗号.Mybatis中的动态 SQL 可以彻底处理这种痛苦.对于动态SQL,最通俗简单的方法就是我们自己在硬编码的时候赋予各种动态行为的判断,而在Mybatis中,用一种强大的动态 SQL 语 言来改进这种情形,这种语言可以被用在任意映射的 SQL 语句中.动态 SQL 元素和使用 JS

Java的MyBatis框架中Mapper映射配置的使用及原理解析

Mapper的内置方法 model层就是实体类,对应数据库的表.controller层是Servlet,主要是负责业务模块流程的控制,调用service接口的方法,在struts2就是Action.Service层主要做逻辑判断,Dao层是数据访问层,与数据库进行对接.至于Mapper是mybtis框架的映射用到,mapper映射文件在dao层用. 下面是介绍一下Mapper的内置方法: 1.countByExample ===>根据条件查询数量 int countByExample(UserE

详解Java的MyBatis框架中SQL语句映射部分的编写

1.resultMap SQL 映射XML 文件是所有sql语句放置的地方.需要定义一个workspace,一般定义为对应的接口类的路径.写好SQL语句映射文件后,需要在MyBAtis配置文件mappers标签中引用,例如: <mappers> <mapper resource="com/liming/manager/data/mappers/UserMapper.xml" /> <mapper resource="com/liming/mana

在Java的MyBatis框架中建立接口进行CRUD操作的方法

以接口操作的方式编程 一般来讲,我们建立映射SQL接口的类时通常会这样: public static void testBasicQuery(int id) { SqlSession session = MybatisUtils.getSqlSession(); try { /* * 此处的david.mybatis.demo.IVisitorOperation.basicQuery必须和下图中配置里面的namespace对应 */ Visitor visitor = (Visitor) ses

详解Java的MyBatis框架中的事务处理

一.MyBatis单独使用时,使用SqlSession来处理事务: public class MyBatisTxTest { private static SqlSessionFactory sqlSessionFactory; private static Reader reader; @BeforeClass public static void setUpBeforeClass() throws Exception { try { reader = Resources.getResourc