深入浅出mybatis分页

news2025/8/12 0:08:29

MyBatis 分页插件 PageHelper

如何使用?

如何使用分页插件

1:添加依赖

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.5</version>
        </dependency>

版本根据需要自行选择
https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter

第一步写一个没有分页的接口。

    @GetMapping("noPage")
    public java.util.List<Doc> list() {
        return mapper.selectList(null);
    }

这个我相信都可以写的出来。

第二步使用PageInfo包裹的接口

    @GetMapping("pageInfo")
    public PageInfo<Doc> pageInfo(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return new PageInfo<>(mapper.selectList(null));
    }

返回值省略list

{
  "total": 20,
  "list": [
  ],
  "pageNum": 2,
  "pageSize": 3,
  "size": 3,
  "startRow": 4,
  "endRow": 6,
  "pages": 7,
  "prePage": 1,
  "nextPage": 3,
  "isFirstPage": false,
  "isLastPage": false,
  "hasPreviousPage": true,
  "hasNextPage": true,
  "navigatePages": 8,
  "navigatepageNums": [
    1,
    2,
    3,
    4,
    5,
    6,
    7
  ],
  "navigateFirstPage": 1,
  "navigateLastPage": 7
}

第三步使用Page包裹返回接口

    @GetMapping("page")
    public Page<Doc> page(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        Page<Doc> page = (Page<Doc>) mapper.selectList(null);
        logger.info(page.toString());
        return page;
    }

测试发现page就是一个分页后的list,不带其他参数。

Page{count=true, pageNum=3, pageSize=4, startRow=8, endRow=12, total=20, pages=5, reasonable=false, 
pageSizeZero=false}

第四步将第三步的page对象放入构造函数。

    @GetMapping("pageToPageInfo")
    public PageInfo<Doc> pageToPageInfo(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        Page<Doc> page = (Page<Doc>) mapper.selectList(null);
        return new PageInfo<>(page);
    }

第五步自定义PageResult作为返回值

@Data
public class PageResult<T> {

    private static final Logger logger = LoggerFactory.getLogger(PageResult.class);

    /**
     * 第几页
     */
    private int pageNum;
    /**
     * 页面大小
     */
    private int pageSize;
    /**
     * 总页数
     */
    private int pages;
    /**
     * 总数
     */
    private long total;
    /**
     * 数据
     */
    private List<T> list;

    /**
     * 构造函数
     *
     * @param list
     */
    public PageResult(List<T> list) {
        if (list instanceof Page) {
            Page<T> page = (Page<T>) list;
            this.pageNum = page.getPageNum();
            this.pageSize = page.getPageSize();
            this.pages = page.getPages();
            this.total = page.getTotal();
        }
        this.list = list;
    }
}
    @GetMapping("pageToPageResult")
    public PageResult<Doc> pageToPageResult(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return new PageResult<>(mapper.selectList(null));
    }
{
  "pageNum": 2,
  "pageSize": 3,
  "pages": 7,
  "total": 20,
  "list": [
  ]
}

借鉴了这段实现逻辑直接从Page中拿到所需参数。

在这里插入图片描述
之所以我们自定义的PageResult可以成功是因为 list instanceof Page 这一行代码,mapper.selectList 经过处理后返回的不是普通的List而是Page对象。

复杂分页

对象转换

一般来说我们拿到的DO和返回前端的VO不是同一个对象会进行相关处理,比如增删字段,这个时候如何正确分页呢?

先演示一个错误案例

    @GetMapping("changeV1")
    public PageInfo<DocQueryRespVO> changeV1(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<Doc> sourceList = mapper.selectList(null);
        List<DocQueryRespVO> targetList = sourceList.stream().map((source) -> {
            DocQueryRespVO target = new DocQueryRespVO();
            BeanUtils.copyProperties(source, target);
            Integer docType = target.getDocType();
            String msg = DocTypeEnum.getMsgByCode(docType);
            target.setDocTypeName(msg);
            return target;
        }).collect(Collectors.toList());
        return new PageInfo<>(targetList);
    }

对原list每个对象修改字段值

{
  "total": 5,
  "list": [
  ],
  "pageNum": 1,
  "pageSize": 5,
  "size": 5,
  "startRow": 0,
  "endRow": 4,
  "pages": 1,
  "prePage": 0,
  "nextPage": 0,
  "isFirstPage": true,
  "isLastPage": true,
  "hasPreviousPage": false,
  "hasNextPage": false,
  "navigatePages": 8,
  "navigatepageNums": [
    1
  ],
  "navigateFirstPage": 1,
  "navigateLastPage": 1
}
``
可以看到这个total是错误的,应该是二十才对。分析一下为什么返回5。

```java
    public PageInfo(List<? extends T> list) {
        this(list, DEFAULT_NAVIGATE_PAGES);
    }
    public PageInfo(List<? extends T> list, int navigatePages) {
        super(list);
   	}
    public PageSerializable(List<? extends T> list) {
        this.list = (List<T>) list;
        if(list instanceof Page){
            this.total = ((Page<?>)list).getTotal();
        } else {
            this.total = list.size();
        }
    }

依次点进去发现,由于instanceof 失败所以取了list的total导致失效。可以加入代码验证 instanceof 输出。

System.out.println(targetList instanceof Page);

方法一

    @GetMapping("changeV2")
    public PageInfo changeV2(Integer pageNum, Integer pageSize) {
		//省略部分代码
        PageInfo pageInfo = new PageInfo(sourceList);
        pageInfo.setList(targetList);
        return pageInfo;
    }

核心思想,利用泛型直接替换list保留原list中的分页信息。

方法二

    @GetMapping("changeV3")
    public PageInfo<DocQueryRespVO> changeV3(Integer pageNum, Integer pageSize) {     
     	//省略部分代码  
        return PageHelperUtil.pageInfoCopy(sourceList, targetList);
    }

封装一个工具类

    public static <source, target> PageInfo<target> pageInfoCopy(List<source> sList, List<target> tList) {
        if (org.springframework.util.CollectionUtils.isEmpty(sList) ||
                org.springframework.util.CollectionUtils.isEmpty(tList)) {
            return null;
        }
        PageInfo<source> sourcePage = new PageInfo<>(sList);
        PageInfo<target> targetPage = new PageInfo<>(tList);
        org.springframework.beans.BeanUtils.copyProperties(sourcePage, targetPage);
        targetPage.setList(tList);
        return targetPage;
    }

核心思想利用BeanUtils.copyProperties将分页信息拷贝过来,仅仅替换list数据。

手动分页

    public static <T> PageInfo<T> pageManual(List<T> list, int pageNum, int pageSize) {
        PageInfo<T> pageInfo = new PageInfo<>();
        //计算总页数
        int total = list.size();
        //如果总数为0直接返回
        if (total == 0) {
            return pageInfo;
        }
        // 计算最大页数
        int pageNumTotal;
        if (total <= pageSize) {
            pageNumTotal = 1;
        } else {
            pageNumTotal = total % pageSize == 0 ? (total / pageSize) : (total / pageSize) + 1;
        }
        //超出最大页码返回最后一页
        if (pageNum > pageNumTotal) {
            pageNum = pageNumTotal;
        }
        //如果页码 <= 0 返回第一页
        if (pageNum <= 0) {
            pageNum = 1;
        }
        //开始分页
        int st;
        int et;
        // 1 <= pageNum <= pageNumTotal
        if (pageNum < pageNumTotal) {
            st = (pageNum - 1) * pageSize;
            et = st + pageSize;
        } else {
            st = (pageNum - 1) * pageSize;
            et = total;
        }
        //subList包含st-et-1
        List<T> result = list.subList(st, et);
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);
        pageInfo.setList(result);
        pageInfo.setTotal(total);
        pageInfo.setPages(pageNumTotal);
        pageInfo.setIsLastPage(pageNumTotal == pageSize);
        return pageInfo;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/15320.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于springboot学生管理系统设计与实现

摘  要 目前&#xff0c;借助信息管理系统能够有效解决高校的信息管理问题&#xff0c;对于提高教育管理水平有着非常重要的作用。 因此&#xff0c;有必要建立一个与之相适应的管理信息系统。基于此&#xff0c;本文为了使教师高效地管理学生信息&#xff0c;需要对现代的学…

【LeetCode-中等】221. 最大正方形(详解)

题目 在一个由 0 和 1 组成的二维矩阵内&#xff0c;找到只包含 1 的最大正方形&#xff0c;并返回其面积。 力扣原题链接 方法1&#xff1a;暴力 暴力法一般不是最优解&#xff0c;但是可以拿来练手 由于正方形的面积等于边长的平方&#xff0c;因此要找到最大正方形的面积&…

【C++】C++基础知识(八)---结构体

C基础知识&#xff08;八&#xff09;1. 定义与使用2. 结构体数组3. 结构体指针4. 结构体嵌套5. 结构体作函数参数6. 结构体中const使用场景7. 结构体使用案例1. 定义与使用 结构体定义&#xff1a; ------结构体属于用户自定义的数据类型&#xff0c;允许用户存储不同的数据类…

元宇宙持续升温,金蝶推出数字员工破圈而来

作者 | 伍杏玲 “金小蝶&#xff0c;请分析今年企业销售事业部的业绩”。 话音刚落&#xff0c;大屏幕展开一张张账务报表&#xff0c;一位身着西装&#xff0c;举止大方得体的数字人条理清晰地回复&#xff1a;“截至今年10月&#xff0c;企业销售事业部在签单金额、新签收入…

数字化转型过程中,企业如何搭建好数据安全?

在企业数字化转型变革中&#xff0c;确保数据安全是企业的责任也是重任。“数据安全”关乎企业数字化发展和未来的商业模式及竞争力&#xff0c;如何在企业数字化转型过程中搭建好“数据安全”的保障&#xff1f; 一、建立数据安全保护意识 互联网时代&#xff0c;有各种各样、…

Vue--》详解Vue组件生命周期的三个阶段

目录 组件生命周期 创建阶段 beforeCreate阶段&#xff1a; created阶段&#xff1a; beforeMount阶段&#xff1a; mounted阶段&#xff1a; 运行阶段 beforeUpdate阶段&#xff1a; updated阶段&#xff1a; 销毁阶段 beforeDestroy阶段&#xff1a; destroyed阶…

windows工作窗口太多,需要频繁切换?摸鱼利器你必须了解下

当我们创作一份内容需要使用到不同窗口的信息时&#xff0c;无比苦恼的就是窗口需要频繁切换了&#xff0c;并且当我们需要参照某个窗口时&#xff0c;这时如果可以把窗口置顶甚至透明窗口效率翻倍&#xff01; WindowTop 是一款窗口自定义设置工具&#xff0c;可将任意窗口置…

[附源码]计算机毕业设计JAVA购买车票系统

[附源码]计算机毕业设计JAVA购买车票系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis M…

怎么把加密的PDF解密?安利几个办公小技巧

大家都知道给pdf文件加密是对文件的一种保护措施&#xff0c;但是如果我们需要对其进行频繁的编辑改动的话&#xff0c;加了密的pdf文件操作起来就很不方便&#xff0c;因为每次的打开都需要输入密码&#xff0c;这个操作其实很浪费时间&#xff0c;其实我只需要将其解密就好了…

用pageOffice文档控件实现 office文档在线编辑

第三方文档控件&#xff0c;pageOffice 系统开发中经常要处理办公文档&#xff0c;如果word&#xff0c;excel&#xff0c;ppt&#xff0c;编辑整理&#xff0c;保存&#xff0c;归档。 开发市场上也有很多第三文文档控件&#xff0c;多年的总结&#xff0c;还是认为pageOffi…

Unity学习之Shader

Shader 是用来实现图像渲染的&#xff0c;用来替代固定渲染管线的可编辑程序。其中Vertex Shader&#xff08;顶点着色器&#xff09;主要负责顶点的几何关系等的运算&#xff0c;Pixel Shader&#xff08;像素着色器&#xff09;主要负责片元颜色等的计算。顶点Shader负责改变…

【毕业设计】微信小程序商城购物系统

文章目录0 前言1 项目介绍1.1 代码工程结构1.2 前端技术1.3 后端技术1.4 实现功能1.4.1 会员管理1.4.2 商城配置1.4.3 商品编辑1.4.4 推广管理1.4.5 订单管理1.4.6 系统管理1.4.7 短信服务平台2 运行效果2.1 前端效果2.2 后端效果3 实现部分源码3.1 前端布局3.2 后端逻辑4 最后…

开箱评测:双十一刚买的云服务器,到底好不好用?

目录前言1. 何为HECS2. 核心特色2.1 易搭建2.2 更实惠2.3 易维护2.4 更安全3. 实践场景3.1 宝塔面板3.2 软件开发3.3 运维部署前言 对开发者和企业来说&#xff0c;双十一首先要购买什么&#xff1f;那必是云服务器。 云服务器&#xff08;Elastic Cloud Server, ECS&#xff…

数据结构:二叉树基础

文章目录一.二叉树的概念及结构1.1概念1.2特殊的二叉树二.二叉树的性质三.小练习3.13.23.3一.二叉树的概念及结构 不熟悉树这个结构的可以看看数据结构:树这篇文章。 1.1概念 一棵二叉树是结点的一个有限集合&#xff0c;该集合: 为空由一个根节点加上两棵别称为左子树和右…

Android动画之帧动画

在Android开发时&#xff0c;为了实现一些动态的炫酷的效果&#xff0c;我们常用到帧动画&#xff0c;View动画&#xff08;补间动画&#xff09;和属性动画&#xff0c;今天就来总结下我在使用帧动画的实现方式。 1、什么是帧动画&#xff1f; 帧动画就是顺序播放一组预先定…

什么是IO

java.io.File类&#xff1a;文件和文件目录路径的抽象表示形式&#xff0c;与平台无关 File 能新建、删除、重命名文件和目录&#xff0c;但 File 不能访问文件内容本身。 如果需要访问文件内容本身&#xff0c;则需要使用输入/输出流。 想要在Java程序中表示一个真实存在的文…

谈谈RabbitMQ的五种消息模型以及SpringAMQP的使用

目录一、前言1. RabbitMQ中的基本概念2. docker部署RabbitMQ3. AMQP与JMS的简单介绍4. 演示demo搭建结构二、Basic Queue三、Work Queue四、发布订阅模式1. Fanout2. Direct3. Topic五、消息转换器1. 默认转换器2. 配置JSON转换器一、前言 1. RabbitMQ中的基本概念 message 消…

逻辑回归损失函数原理笔记

损失函数&#xff1a; 之前一直想不明白这个式子为什么可以当损失函数。所以记录一下。 首先&#xff0c;假如一个属于1类的样本&#xff0c;经过预测&#xff0c;h(x)0.3,得出0.3的概率是属于1类&#xff0c;也就是0.7的概率是属于0类&#xff0c;那么其误差就是0.7。 相反&…

配置七牛云的自定义域名以及配置域名CNAME

背景&#xff1a;最近在使用七牛云的过程中发现一个问题&#xff0c;七牛云的测试域名是有时效限制的且到期后重新申请会改变&#xff0c;自己业务方生产和测试环境需要使用固定的域名来配置图片访问&#xff0c;这时就需要绑定到自己的域名了。 1、配置七牛云自定义域名 这个…

学Golang,看这一篇

去年学了一遍 Golang&#xff0c;发现都给整忘了&#xff0c; 好饭不怕晚&#xff0c;再次二刷。 其实学好 Golang 并不难&#xff0c;关键是要找到它和其它语言不同和众里寻他千百度相通的微妙之处&#xff0c;就能很优雅地使用 Golang&#xff0c;以下会涉及较多知识点。特殊…