MyBatis-Plus 分页查询以及自定义sql分页

MyBatis-Plus 分页查询以及自定义sql分页一、引言分页查询每个人程序猿几乎都使用过,但是有部分同学不懂什么是物理分页和逻辑分页。物理分页:相当于执行了limit分页语句,返回部分数据。物理分页只返回部分数据占用内存小,能够获取数据库最新的状态,实施性比较强,一般适用于数据量比较大,数据更新比较频繁的场景。逻辑分页:一次性把全部的数据取出来,通过程序进行筛选数据。如果数据量大的情况下会消耗大量的内存,由于逻辑分页只需要读取数据库…

大家好,又见面了,我是你们的朋友全栈君。

一、引言

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

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

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

那么MP中的物理分页怎么实现呢? 往下看往下看

二、配置

创建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();
    }
}

三、具体分页实现

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

现在我们有需求只要查询数据即可, 不关心总记录数等,如果使用默认的方式就消耗不必要的性能。那么解决办法也是很简单的,只需要在创建page对象时传入第三个参数为false即可

 Page<User> page = new Page<>(1,2,false);

四、自定义sql分页查询

有时候查询的数据难免会出现多表连接查询,或者是一些复杂的sql语句,但是这些语句也是需要支持分页查询的,

先定义查询接口,第一个参数要是分页的参数,小编这里演示就写简单的sql。

步骤一:在mapper文件中,编写对应的分页查询接口。

步骤二:在xml中编写对应的sql语句,小编这里演示的 “${ew.customSqlSegment}”,这个是如果你想自定义的sql语句,也想使用wrapper查询条件构造器,则需要在mapper接口中添加参数,以及xml中也要有固定。 

    /**
     * 自定义sql分页
     * @param page
     * @param queryWrapper 看这里看这里,如果自定义的方法中需要用到wrapper查询条件,需要这样写
     * @return
     */
    IPage<User> selectMyPage(IPage<User> page, @Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">

    <select id="selectMyPage" resultType="com.example.demo.model.User">
        SELECT * FROM user ${ew.customSqlSegment}
    </select>

</mapper>
   /**
     * 自定义sql分页查询
     */
    @Test
    public void selectByMyPage() {
        QueryWrapper<User> wrapper = new QueryWrapper();
        wrapper.like("name", "雨").lt("age", 40);
        Page<User> page = new Page<>(1,2);
        IPage<User> mapIPage = userMapper.selectMyPage(page, wrapper);

        System.out.println("总页数"+mapIPage.getPages());
        System.out.println("总记录数"+mapIPage.getTotal());
        List<User> records = mapIPage.getRecords();
        records.forEach(System.out::println);
    }

五、多表sql分页查询

看评论有小伙伴反馈多表连接查询怎么分页,其实道理都是一样的。

小编以简单的为主,sql如下: his_ipd_encounter、his_user 两张表

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">

    <select id="selectByHisName" resultType="java.lang.String">
        select u.realname from his_ipd_encounter e, his_user u where e.his_uid = u.his_uid
    </select>
    

</mapper>

mapepr如下:需要传入分页的参数,返回的类型也需要是分页对象


/**
 * <p>
 * 用户 Mapper 接口
 * </p>
 *
 * @author IT贱男
 * @since 2019-06-14
 */
public interface UserMapper extends MyMapper<User> {


    /**
     * 多表查询分页
     * @param page
     * @return
     */
    IPage<String> selectByHisName(IPage<User> page);
}

测试如下:通过查看日志,执行的sql加了分页条件的。

   @Test
    public void select(){
        // 创建分页参数
        Page<User> page = new Page<>(1,2);
        IPage<String> result = userMapper.selectByHisName(page);
        // 获取数据
        List<String> records = result.getRecords();
        records.forEach(System.out::println);
        System.out.println("总页数 = "+ result.getPages());
    }
ARNWarn: Could not find @TableId in Class: com.example.demo.model.HisUser.
INFOStarted UserMapperTest in 2.428 seconds (JVM running for 2.959)
select u.realname from his_ipd_encounter e, his_user u where e.his_uid = u.his_uid
DEBUG==>  Preparing: SELECT COUNT(1) FROM his_ipd_encounter e, his_user u WHERE e.his_uid = u.his_uid 
DEBUG==> Parameters: 
TRACE<==    Columns: COUNT(1)
TRACE<==        Row: 117
DEBUG==>  Preparing: select u.realname from his_ipd_encounter e, his_user u where e.his_uid = u.his_uid LIMIT ?,? 
DEBUG==> Parameters: 0(Long), 2(Long)
TRACE<==    Columns: realname
TRACE<==        Row: 胡伯云
TRACE<==        Row: 安元慧
DEBUG<==      Total: 2
 Time:20 ms - ID:com.example.demo.mapper.UserMapper.selectByHisName
Execute SQL:
    com.p6spy.engine.wrapper.PreparedStatementWrapper@61bcbcce

胡伯云
安元慧
总页数 = 59

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/153242.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 成麻结账程序_成麻5元40满怎么算账

    成麻结账程序_成麻5元40满怎么算账1.0版预览地址:http://hudong.miaos.me/majiang/index.html2.0博客直通车:https://www.cnblogs.com/qinyulin/p/13566

    2022年8月2日
    8
  • qt操作json(QT 教程)

    以故事方式来学习如何使用Qt接口来操作JSON数据。

    2022年4月17日
    42
  • 为什么opencv安装成功但import cv2失败_python和opencv

    为什么opencv安装成功但import cv2失败_python和opencv遇到的问题:win10如何安装opencvpycharm中importcv2模块出现错误,找不到该模块处理经过:win10如何安装opencv自己的电脑上已经装有anaconda,下载地址为:https://www.anaconda.com/download/,像numpy等包已经伴随anaconda安装到电脑上了,只需要再安装opencv就行。使用pipinstal…

    2022年8月27日
    6
  • 在移动端避免使用100vh「建议收藏」

    在移动端避免使用100vh「建议收藏」在移动端避免使用100vhCSS中的Viewport单元听起来很棒。如果你想将一个元素设置成全屏高度,你可以设置高度:100vh,这样你就有了一个完美的全屏元素,它会随着视口的改变而改变大小!遗憾的是,事实并非如此。100vh在不同的浏览器的实现方式上也有一点微妙的变化,这使得它几乎毫无用处。最好避免100vh,而是依赖javascript来设置高度,以获得完整的视口体验。核心问题是移动浏览器…

    2022年5月6日
    44
  • 大学《数据库系统》课程设计报告「建议收藏」

    大学《数据库系统》课程设计报告「建议收藏」湖南科技大学计算机科学与工程学院《数据库系统》课程设计题目:教学管理系统专业:计算机科学与技术年级:2017级班级:计科三班学号:170510323姓名:雨萱完成时间:2019年1月3日教务管理系统的分析与实现一.实验目的数据库系统课程设计是为了配合数据库原理及应用开发而…

    2022年5月12日
    23
  • Git克隆远端代码到本地「建议收藏」

    1、在桌面上点击鼠标右键,找到clone选项,出现其中URL是你要访问的地址,directory为文件保存的路径。点击OK2、桌面上会生成一个文件夹3、在此文件夹中,点击鼠标右键,找到GitBashHere,进入到如下页面输入命令第一:gitconfig–globaluser.name“zjut_wzc”第二:gitconfig–globaluser.em…

    2022年4月7日
    162

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号