mybatis&Mysql 分页查询

温故而知新,这里记录一下

一、引言

        分页查询每个人程序猿几乎都使用过,但是有部分同学不懂什么是物理分页和逻辑分页。

        物理分页:

        相当于执行了limit分页语句,返回部分数据。物理分页只返回部分数据占用内存小,能够获取数据库最新的状态,实施性比较强,一般适用于数据量比较大,数据更新比较频繁的场景

        逻辑分页:

        一次性把全部的数据取出来,通过程序进行筛选数据。如果数据量大的情况下会消耗大量的内存,由于逻辑分页只需要读取数据库一次,不能获取数据库最新状态,实施性比较差,适用于数据量小,数据稳定的场合。

二、分页处理方式

2.1、MybatisPageHelper组件

        常用的分页组件有MybatisPageHelper等,分页原理为先执行原SQL+limit语句,再执行select count(*) from xxx where xxx语句。

        一共执行了两次,进行了两次数据的筛选和过滤

2.1.1、MybatisPlusConfig配置

创建MybatisPlusConfig配置类,需要配置分页插件,小编使用的Spring boot配置方式。

/**
 * @Auther: IT贱男
 * @Date: 2019/6/12 15:06
 * @Description: MybatisPlus配置类
 */
@Configuration
public class MyBatisPlusConfig {
 
    /**
     * 分页插件
     * @return
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}


2.1.2、具体分页实现

MP的Wrapper提供了两种分页查询的方式,源码如下:

 /**
     * 根据 entity 条件,查询全部记录(并翻页)
     *
     * @param page         分页查询条件(可以为 RowBounds.DEFAULT)
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
 
    /**
     * 根据 Wrapper 条件,查询全部记录(并翻页)
     *
     * @param page         分页查询条件
     * @param queryWrapper 实体对象封装操作类
     */
    IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

可见两个分页方法参数都是一致的,只是返回参数略有不同,具体选择根据实际业务为准。

  /**
     * 分页查询
     */
    @Test
    public void selectByPage() {
        QueryWrapper<User> wrapper = new QueryWrapper();
        wrapper.like("name", "雨").lt("age", 40);
 
        Page<User> page = new Page<>(1,2);
 
        //IPage<User> userIPage = userMapper.selectPage(page, wrapper);
 
        IPage<Map<String, Object>> mapIPage = userMapper.selectMapsPage(page, wrapper);
 
 
        System.out.println("总页数"+mapIPage.getPages());
        System.out.println("总记录数"+mapIPage.getTotal());
        List<Map<String, Object>> records = mapIPage.getRecords();
        records.forEach(System.out::println);
    }

以上分页查询执行sql如下,先是查询了一次总记录数,然后在查询的数据。

DEBUG==>  Preparing: SELECT COUNT(1) FROM user WHERE name LIKE ? AND age < ? 
DEBUG==> Parameters: %雨%(String), 40(Integer)
TRACE<==    Columns: COUNT(1)
TRACE<==        Row: 2
DEBUG==>  Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE name LIKE ? AND age < ? LIMIT ?,? 
DEBUG==> Parameters: %雨%(String), 40(Integer), 0(Long), 2(Long)
TRACE<==    Columns: id, name, age, email, manager_id, create_time
TRACE<==        Row: 2, 张雨琪, 31, zjq@baomidou.com, 1088248166370832385, 2019-01-14 09:15:15
TRACE<==        Row: 3, 刘红雨, 31, lhm@baomidou.com, 1088248166370832385, 2019-01-14 09:48:16
DEBUG<==      Total: 2
总页数1
总记录数2

可以看出,质量量两条查询语句:

  • SELECT COUNT(1) FROM user WHERE name LIKE ? AND age < ?
  • SELECT id,name,age,email,manager_id,create_time FROM user WHERE name LIKE ? AND age < ? LIMIT ?,?

2.2 mysql SQL_CALC_FOUND_ROWS & FOUND_ROWS

        可以使用MySQL “SQL_CALC_FOUND_ROWS & FOUND_ROWS()” ,只需进行一次数据的筛选和过滤。(FOUND_ROWS()函数用于统计limit之前查找到的行数)。

2.2.1 例子

实际项目中使用
(1)UserMapper.xml

<resultMap type="com.sys.entity.User" id="UserResult">
    <id     property="userId"       column="user_id"      />
    <result property="deptId"       column="dept_id"      />
    <result property="userName"     column="user_name"    />
    <result property="nickName"     column="nick_name"    />
    <result property="roleIds"     column="role_ids"    />
    <result property="password"     column="password"     />
    <result property="createBy"     column="create_by"    />
    <result property="createTime"   column="create_time"  />
    <result property="updateBy"     column="update_by"    />
    <result property="updateTime"   column="update_time"  />
    <result property="remark"       column="remark"       />
</resultMap>

<resultMap type="java.lang.Integer" id="count">
    <result column="total"/>
</resultMap>

<select id="selectList" resultMap="UserResult,count">
   SELECT SQL_CALC_FOUND_ROWS a.user_id,a.user_name,a.nick_name,dept_name ,c.role_name
   FROM sys_user a
    LEFT JOIN sys_dept b on a.dept_id=b.dept_id
    LEFT JOIN sys_role c on a.role_ids=c.role_id
   <where>
       <if test="userName != null and userName != ''">
           AND u.user_name like concat('%', #{userName}, '%')
       </if>
       <if test="deptName != null and deptName != ''">
           AND d.dept_name like concat('%', #{deptName}, '%')
       </if>
   </where>
   order by create_time desc
   LIMIT ${pageSize * (pageNum-1)},${pageSize};
   SELECT FOUND_ROWS() AS total;
</select>


(2)UserMapper.java

List<Object> selectList(@Param("pageSize") Integer pageSize,
                        @Param("pageNum") Integer pageNum,
                        @Param("userName") String userName,
                        @Param("deptName") String deptName);


(3)UserService.java

public List<Object> selectList(Integer pageSize,Integer pageNum,String userName,String deptName) {
    return userMapper.selectList(pageSize,pageNum,userName,deptName);
}


(4)UserController.java

/**
     * 获取用户列表
     * @return 用户列表
     */
    @GetMapping("/list")
    public ResultVo list(Integer pageSize, Integer pageNum,String userName,String deptName){
        
        List<Object> objList = userService.selectList(pageSize, pageNum, userName,deptName);
        
        List<User> list = (List<User>) objList.get(0);
        
        int count = ((List<Integer>) objList.get(1)).get(0);//总数
        
        Page<User> page = new Page<>(pageSize, pageNum);
        page.setSize(pageSize);
        page.setCurrent(pageNum);
        page.setTotal(count);
        //计算分页总页数
        page.setPages(count %10 == 0 ? count/10 :count/10+1);
        page.setRecords(list);
        return ResultVoUtil.success(page);
    }


最后,还需要在yml或propertis配置文件中,配置数据库连接池那里,在 url 中,加上 allowMultiQueries=true
 

2.3、mysql-mybatis-pagination组件

        mysql-mybatis-pagination是一个基于MySQL方言 “SQL_CALC_FOUND_ROWS & FOUND_ROWS()” 的轻量级分页组件。

<dependency>
    <groupId>io.github.flashvayne</groupId>
    <artifactId>mysql-mybatis-pagination</artifactId>
    <version>1.0.1</version>
</dependency>

        项目github地址:mysql-mybatis-pagination

MySQL分页组件mysql-mybatis-pagination|Springboot|Mybatis | Vayne的博客

三、参考

MyBatis或MyBatis-plus中分页查询同时查询数据和总数量_mybatisplus分页查询到的总数据量-CSDN博客

MySQL分页组件mysql-mybatis-pagination|Springboot|Mybatis | Vayne的博客

Mybatis分页查询和总条数避免查询两次的方法 - 简书

https://www.cnblogs.com/FlyGoldfish/articles/16615357.html

相关推荐

  1. springboot查询

    2024-01-12 14:56:05       35 阅读
  2. sql查询

    2024-01-12 14:56:05       8 阅读
  3. 【MyBatis-Plus】查询

    2024-01-12 14:56:05       43 阅读
  4. mybatis&Mysql 查询

    2024-01-12 14:56:05       39 阅读
  5. 【数据库】MySQL查询

    2024-01-12 14:56:05       13 阅读
  6. PageHelper实现查询

    2024-01-12 14:56:05       14 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-12 14:56:05       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-12 14:56:05       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-12 14:56:05       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-12 14:56:05       18 阅读

热门阅读

  1. 算法习题练习

    2024-01-12 14:56:05       28 阅读
  2. .net core 6 集成和使用 mongodb

    2024-01-12 14:56:05       36 阅读
  3. 【大数据面试】常见数仓建模面试题附答案

    2024-01-12 14:56:05       32 阅读
  4. vue3知识盲点总结

    2024-01-12 14:56:05       28 阅读
  5. js中console.log()的使用方法

    2024-01-12 14:56:05       35 阅读
  6. 箭头函数与普通函数的差异

    2024-01-12 14:56:05       33 阅读
  7. Django身份验证初试

    2024-01-12 14:56:05       43 阅读