当前位置: 首页 > news >正文

MybatisPlus的分页插件

PaginationInnerInterceptor

此插件是核心插件,目前代理了 Executor#query 和 Executor#update 和 StatementHandler#prepare 方法。

在SpringBoot环境中配置方式如下:

/*** @author giserDev* @description 配置分页插件、方言、mapper包扫描等* @date 2023-12-13 23:23:35*/
@Configuration
@MapperScan("com.giser.mybatisplus.mapper")
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return mybatisPlusInterceptor;}}

测试分页功能:


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.giser.mybatisplus.mapper.UserMapper;
import com.giser.mybatisplus.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;/*** @author giserDev* @description* @date 2023-12-13 23:28:43*/
@Slf4j
@SpringBootTest
public class MyBatisPlusPluginsTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testMyBatisPlusPage(){Page<User> page = new Page<>(1,3);userMapper.selectPage(page, null);log.info("分页查询结果为:{}", page);}}

如何自定义分页?

# mybatis-plus配置
mybatis-plus:configuration:# 引入日志log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:# 配置MybatisPlus操作的表的前缀table-prefix: t_# 配置MybatisPlus的主键生成策略id-type: assign_id# 指定类型别名type-aliases-package: com.giser.mybatisplus.pojo

在Mapper接口中定义分页方法:

@Repository
public interface UserMapper extends BaseMapper<User> {/*** 利用MybatisPlus的分页功能* @param page 分页对象,必须在第一个参数位置,传递参数 Page 即自动分页* @param userName 查询条件* @return 结果*/Page<User> selectPageByName(@Param("page") Page<User> page, @Param("userName") String userName);}

在Mapper.xml文件中实现分页语句:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.giser.mybatisplus.mapper.UserMapper"><select id="selectPageByName" resultType="User">select * from user where user_name = #{userName}</select></mapper>

分页测试:


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.giser.mybatisplus.mapper.UserMapper;
import com.giser.mybatisplus.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@Slf4j
@SpringBootTest
public class MyBatisPlusPluginsTest {@Autowiredprivate UserMapper userMapper;/*** ==>  Preparing: SELECT COUNT(*) AS total FROM user WHERE is_deleted = 0* ==> Parameters:* <==    Columns: total* <==        Row: 25* <==      Total: 1* ==>  Preparing: SELECT id,user_name AS name,age,email,is_deleted FROM user WHERE is_deleted=0 LIMIT ?* ==> Parameters: 3(Long)* <==    Columns: id, name, age, email, is_deleted* <==        Row: 1, Jone, 18, test1@baomidou.com, 0* <==        Row: 2, 窃听风云, 23, giserDev@163.com, 0* <==        Row: 3, Tom, 28, test3@baomidou.com, 0* <==      Total: 3* Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3a109ff7]* 分页查询结果为:com.baomidou.mybatisplus.extension.plugins.pagination.Page@5ee77baf* 分页查询记录结果为:[User(id=1, name=Jone, age=18, email=test1@baomidou.com, isDeleted=0), User(id=2, name=窃听风云, age=23, email=giserDev@163.com, isDeleted=0), User(id=3, name=Tom, age=28, email=test3@baomidou.com, isDeleted=0)]* 分页查询记录条数为:25* 分页查询当前页码为:1* 分页查询每页大小为:3*/@Testpublic void testMyBatisPlusPage(){Page<User> page = new Page<>(1,3);userMapper.selectPage(page, null);log.info("分页查询结果为:{}", page);log.info("分页查询记录结果为:{}", page.getRecords());log.info("分页查询记录条数为:{}", page.getTotal());log.info("分页查询当前页码为:{}", page.getCurrent());log.info("分页查询每页大小为:{}", page.getSize());}/*** ==>  Preparing: SELECT COUNT(*) AS total FROM user WHERE user_name = ?* ==> Parameters: 李雷(String)* <==    Columns: total* <==        Row: 1* <==      Total: 1* ==>  Preparing: select * from user where user_name = ? LIMIT ?* ==> Parameters: 李雷(String), 3(Long)* <==    Columns: id, user_name, age, email, is_deleted* <==        Row: 1734579107187970050, 李雷, 12, null, 1* <==      Total: 1* Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@a316f6b]* 分页查询结果为:com.baomidou.mybatisplus.extension.plugins.pagination.Page@48368a08* 分页查询记录结果为:[User(id=1734579107187970050, name=null, age=12, email=null, isDeleted=1)]* 分页查询记录条数为:1* 分页查询当前页码为:1* 分页查询每页大小为:3*/@Testvoid testAutoPage(){Page<User> page = new Page<>(1,3);userMapper.selectPageByName(page, "李雷");log.info("分页查询结果为:{}", page);log.info("分页查询记录结果为:{}", page.getRecords());log.info("分页查询记录条数为:{}", page.getTotal());log.info("分页查询当前页码为:{}", page.getCurrent());log.info("分页查询每页大小为:{}", page.getSize());}}
问题:分页参数处理原理

拦截执行的语句
org.apache.ibatis.plugin.Plugin#invoke

if (methods != null && methods.contains(method)) {
return interceptor.intercept(new Invocation(target, method, args));
}

com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor#intercept

    @Overridepublic Object intercept(Invocation invocation) throws Throwable {// ...for (InnerInterceptor query : interceptors) {// com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor#willDoQuery// willDoQuery(),先判断总条数,决定是否执行sql语句if (!query.willDoQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql)) {return Collections.emptyList();}// beforeQuery(),处理排序、分页方言query.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
}// ...
    @Overridepublic boolean willDoQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {// 查找分页参数IPage<?> page = ParameterUtils.findPage(parameter).orElse(null);if (page == null || page.getSize() < 0 || !page.searchCount()) {return true;}// ...// 组装统计语句,判断总条数long total = 0;if (CollectionUtils.isNotEmpty(result)) {// 个别数据库 count 没数据不会返回 0Object o = result.get(0);if (o != null) {total = Long.parseLong(o.toString());}}page.setTotal(total);// protected boolean continuePage(IPage<?> page)// 返回是否继续执行后面的查询语句,执行则返回true,否则返回falsereturn continuePage(page);}

willDoQuery()方法中包含查询分页参数的逻辑,如下:

/*** 查找分页参数** @param parameterObject 参数对象* @return 分页参数*/
public static Optional<IPage> findPage(Object parameterObject) {if (parameterObject != null) {// 若参数类型为Map,则从map中查找类型为IPage的参数,作为分页参数if (parameterObject instanceof Map) {Map<?, ?> parameterMap = (Map<?, ?>) parameterObject;for (Map.Entry entry : parameterMap.entrySet()) {if (entry.getValue() != null && entry.getValue() instanceof IPage) {return Optional.of((IPage) entry.getValue());}}} else if (parameterObject instanceof IPage) {// 若参数类型为IPage,则直接返回,作为分页参数return Optional.of((IPage) parameterObject);}}return Optional.empty();
}

com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor#beforeQuery

@Overridepublic void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {IPage<?> page = ParameterUtils.findPage(parameter).orElse(null);if (null == page) {return;}// 处理 orderBy 拼接boolean addOrdered = false;String buildSql = boundSql.getSql();List<OrderItem> orders = page.orders();if (CollectionUtils.isNotEmpty(orders)) {addOrdered = true;buildSql = this.concatOrderBy(buildSql, orders);}// size 小于 0 且不限制返回值则不构造分页sqlLong _limit = page.maxLimit() != null ? page.maxLimit() : maxLimit;if (page.getSize() < 0 && null == _limit) {if (addOrdered) {PluginUtils.mpBoundSql(boundSql).sql(buildSql);}return;}handlerLimit(page, _limit);// 查找方言,在配置分页插件时,设置了DbType,此时可确定方言,如此时返回的是com.baomidou.mybatisplus.extension.plugins.pagination.dialects.MySqlDialectIDialect dialect = findIDialect(executor);final Configuration configuration = ms.getConfiguration();// 构造分页语句!!!com.baomidou.mybatisplus.extension.plugins.pagination.dialects.IDialect#buildPaginationSql// 此时dialect为MySqlDialect,会调用com.baomidou.mybatisplus.extension.plugins.pagination.dialects.MySqlDialect#buildPaginationSql来构造sqlDialectModel model = dialect.buildPaginationSql(buildSql, page.offset(), page.getSize());// ...// 此处绑定执行的sql语句model.getDialectSql()mpBoundSql.sql(model.getDialectSql());mpBoundSql.parameterMappings(mappings);}

com.baomidou.mybatisplus.extension.plugins.pagination.dialects.MySqlDialect#buildPaginationSql

public class MySqlDialect implements IDialect {@Overridepublic DialectModel buildPaginationSql(String originalSql, long offset, long limit) {StringBuilder sql = new StringBuilder(originalSql).append(" LIMIT ").append(FIRST_MARK);if (offset != 0L) {sql.append(StringPool.COMMA).append(SECOND_MARK);return new DialectModel(sql.toString(), offset, limit).setConsumerChain();} else {return new DialectModel(sql.toString(), limit).setConsumer(true);}}
}

相关文章:

MybatisPlus的分页插件

PaginationInnerInterceptor 此插件是核心插件,目前代理了 Executor#query 和 Executor#update 和 StatementHandler#prepare 方法。 在SpringBoot环境中配置方式如下&#xff1a; /*** author giserDev* description 配置分页插件、方言、mapper包扫描等* date 2023-12-13 …...

保障网络安全:了解威胁检测和风险评分的重要性

在当今数字时代&#xff0c;网络安全问题变得愈发突出&#xff0c;而及时发现和迅速应对潜在威胁成为保障组织信息安全的首要任务。令人震惊的是&#xff0c;根据2023年的数据&#xff0c;平均而言&#xff0c;检测到一次网络入侵的时间竟然长达207天。这引起了对安全策略和技术…...

3D摄影棚布光:Set A Light 3D Studio

Set A Light 3D Studio是一款专业的灯光模拟软件&#xff0c;旨在帮助摄影师和电影制片人在电脑上进行虚拟灯光布置和场景模拟&#xff0c;以实现更加精准和高质量的拍摄效果。该软件提供了丰富的灯光和场景模型&#xff0c;支持灵活调整光源位置、强度、颜色和效果等参数&…...

#HarmonyOS:应用的包名配置--应用图标和标签配置--配置链接

配置相关 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/application-component-configuration-stage-0000001478340869-V2 应用的包名配置 应用需要在工程的AppScope目录下的app.json5配置文件中配置bundleName标签&#xff0c;该标签用于标识应用的唯…...

docker小白第三天

docker小白第三天 docker为什么会比虚拟机快 1、docker有着比虚拟机更少的抽象层。不需要Hypervisor实现硬件资源虚拟化&#xff0c;运行在docker容器上的程序直接使用的都是实际物理机的硬件资源&#xff0c;因此在CPU、内存利用率上docker将会在效率上有明显优势。 2、dock…...

FFmpegd的AVBSF

本章主要介绍AVBSF 文章目录 结构体定义对外函数常见的过滤器 从名字我们可以知道这是个码流过滤器&#xff0c;我们最常用的是一个叫做h264_mp4toannexb_bsf的东东 这个过滤器的作用是把h264以MP4格式的NALU转换为annexb&#xff08;0x000001&#xff09; const AVBitStreamF…...

深圳三男子写字楼内吸烟被罚,快用富维AI神器,实时监控防火灾

最近&#xff0c;在深圳&#xff0c;一专项控烟督查组在福田区新华保险大厦发现三名男子在写字楼内楼道违法吸烟&#xff0c;并对其进行了现场处罚。根据《控烟条例》&#xff0c;这类室内区域严禁吸烟&#xff0c;但人们往往忽视这一规定&#xff0c;从而引发潜在的安全风险。…...

有哪些已经上线的vue商城项目?

前言 下面是一些商城的项目&#xff0c;需要练手的同学可以挑选一些来练&#xff0c;废话少说&#xff0c;让我们直接开始正题~~ 1、newbee-mall-vue3-app 是一个基于 Vue 3 和 TypeScript 的电商前端项目&#xff0c;它是 newbee-mall 项目的升级版。该项目包含了商品列表、…...

Nginx服务器配置SSL证书

本文将全面介绍如何在Nginx或Tengine服务器配置SSL证书&#xff0c;具体包括下载和上传证书文件&#xff0c;在Nginx上配置证书文件、证书链和证书密钥等参数&#xff0c;以及安装证书后结果的验证。成功配置SSL证书后&#xff0c;您将能够通过HTTPS加密通道安全访问Nginx服务器…...

【JVM从入门到实战】(六)类加载器的双亲委派机制

一、双亲委派机制 在Java中如何使用代码的方式去主动加载一个类呢&#xff1f; 方式1&#xff1a;使用Class.forName方法&#xff0c;使用当前类的类加载器去加载指定的类。 方式2&#xff1a;获取到类加载器&#xff0c;通过类加载器的loadClass方法指定某个类加载器加载。 …...

SpringCloud面试题及答案(最新50道大厂版,持续更新)

在Java开发中&#xff0c;Spring Cloud作为微服务架构的关键组成部分&#xff0c;为了帮助广大Java技术爱好者和专业开发人员深入理解Spring Cloud&#xff0c;本文《SpringCloud面试题及答案&#xff08;最新50道大厂版&#xff0c;持续更新&#xff09;》提供了最前沿、最实用…...

Next.js 的设计理念

Next.js 的设计理念&#xff1a;简洁、强大与高效 Next.js 是一个流行的 React 框架&#xff0c;由 Vercel 公司开发。它的设计理念是简洁、强大和高效&#xff0c;这种理念贯穿于 Next.js 的所有功能中。下面我们将深入探讨这三个设计理念。 简洁 Next.js 的一个核心设计理…...

26、文件包含

文章目录 一、文件包含1.1 概念1.2 PHP文件包含原理1.3 文件包含重要函数1.4 文件包含利用条件 二、文件包含漏洞利用2.1 文件包含分类2.2 常见敏感文件2.3 包含Apache日志文件2.4 常见中间件的日志路径2.5 包含其他日志文件2.5.1 SSH日志文件2.5.2 Session文件 三、PHP封装伪协…...

飞天使-linux操作的一些技巧与知识点4-ansible常用的技巧,配置等

文章目录 ansible配置文件的优先级尝试开始进行操作ansible常用模块ansible 的playbook示例安装phpplaybook中变量的引用 ansible yum install -y ansible 测试是否可用 ansible localhost -m ping /etc/ansible/ansible.cfg &#xff1a;主配置文件&#xff0c;配置 ansible…...

Stable Diffusion 源码解析(1)

参考1&#xff1a;https://blog.csdn.net/Eric_1993/article/details/129393890 参考2&#xff1a;https://zhuanlan.zhihu.com/p/613337342 1.StableDiffusion基本原理1.1 UNetModel、FrozenCLIP 模型1.2 DDPM、DDIM、PLMS算法 2. Runwayml SD 源码2.1 Img2Img Pipeline2.2 DD…...

java.lang.ClassNotFoundException:javax.xml.bind.DatatypeConverter 报错解决

问题原因: 这有可能是因为SpringBoot项目结合jwt进行用户登录时出现的问题&#xff0c;因为jdk版本太高导致的 解决办法: 方法一: 降低jdk版本 检查JDK版本,如果你是JDK17版本,就降到JDK8版本 方案二:在meven中添加依赖 注意: 如果2.3.1的版本不生效,则使用2.3.0的版本 <…...

Python学习笔记-类

1 定义类 类是函数的集合&#xff0c;class来定义类 pass并没有实际含义&#xff0c;只是为了代码能执行通过&#xff0c;不报错而已&#xff0c;相当于在代码种占一个位置&#xff0c;后续完善 类是对象的加工厂 2.创建对象 carCar()即是创建对象的过程 3、类的成员 3.1 实例…...

了解如何在linux使用podman管理容器

本章主要介绍使用 podman 管理容器。 了解什么是容器&#xff0c;容器和镜像的关系 安装和配置podman 拉取和删除镜像 给镜像打标签 导出和导入镜像 创建和删除镜像 数据卷的使用 管理容器的命令 使用普通用户管理容器 使用普通用户管理容器 对于初学者来说&#xff0c;不太容…...

SQL命令---修改字段的数据类型

介绍 使用sql语句修改字段的数据类型。 命令 alter table 表明 modify 字段名 数据类型;例子 有一张a表&#xff0c;表里有一个id字段&#xff0c;长度为11。使用命令将长度修改为12 下面使用命令进行修改&#xff1a; alter table a modify id int(12) NOT NULL;下面使修…...

一键提取微信聊天记录,生成HTML、Word文档永久保存,还能生成微信年度聊天报告

不知道生活中你有没有遇到过这种情况&#xff0c;聊天记录不完整&#xff0c;有的在手机上&#xff0c;有的在电脑上&#xff0c;搜索起来很烦。那有没有一种办法可以把微信聊天记录统一呢&#xff1f;当然是有的。下面&#xff0c;就让我们一起来看一下怎么操作。 先看效果 操…...

离线语音智能处理平台Buzz:本地化音频转文本全攻略

离线语音智能处理平台Buzz&#xff1a;本地化音频转文本全攻略 【免费下载链接】buzz Buzz transcribes and translates audio offline on your personal computer. Powered by OpenAIs Whisper. 项目地址: https://gitcode.com/GitHub_Trending/buz/buzz 在当今信息驱动…...

Redis 相关命令详解及其原理

Redis 相关命令详解及其原理 文章目录Redis 相关命令详解及其原理1. Redis 简介2. Redis 安装2.1 包管理器安装2.2 源码编译安装2.4 验证安装3. Redis 基础原理3.1 单线程模型3.2 底层数据结构概述4. 数据类型详解4.1 String&#xff08;字符串&#xff09;底层存储结构常用命令…...

计算机图形学面试突击:Cohen-Sutherland编码裁剪的10种边界情况详解

计算机图形学面试突击&#xff1a;Cohen-Sutherland编码裁剪的10种边界情况详解 在计算机图形学的面试中&#xff0c;直线段裁剪算法是高频考点之一。Cohen-Sutherland算法作为经典解决方案&#xff0c;其核心在于通过编码和位运算快速判断线段与裁剪窗口的关系。本文将深入剖析…...

春联生成模型-中文-base:5分钟快速部署,小白也能轻松定制专属春联

春联生成模型-中文-base&#xff1a;5分钟快速部署&#xff0c;小白也能轻松定制专属春联 春节快到了&#xff0c;家家户户都要贴春联。可每年都写“福星高照”、“万事如意”&#xff0c;是不是有点腻了&#xff1f;想写点有新意的&#xff0c;又怕自己文采不够。别担心&…...

intv_ai_mk11应用场景:新媒体运营——热点事件评论草稿、标题党生成、互动话术

intv_ai_mk11在新媒体运营中的三大实战应用 1. 新媒体运营的痛点与AI解决方案 新媒体运营人员每天面临三大核心挑战&#xff1a;快速跟进热点事件、创作吸引眼球的标题、设计有效的互动话术。传统人工创作方式不仅耗时耗力&#xff0c;而且难以保证持续高质量输出。 intv_ai…...

告别重复编码:用快马AI自动生成软件库e7c9的高效调用代码

作为一名经常和第三方库打交道的开发者&#xff0c;我深刻体会到手动编写调用代码的繁琐。尤其是像e7c9这样功能强大的软件库&#xff0c;虽然封装完善&#xff0c;但每次调用都需要反复查阅文档、处理边界情况&#xff0c;效率实在不高。最近尝试用InsCode(快马)平台的AI辅助生…...

告别人工筛选!用Word2vec构建主题词库,我们拿“网络暴力”关键词试了试

智能主题词库构建实战&#xff1a;用Word2vec挖掘语义关联词汇 在信息爆炸的时代&#xff0c;内容运营和产品经理们常常面临一个共同挑战&#xff1a;如何从海量文本中快速识别和归类相关主题内容。传统的人工筛选方法不仅效率低下&#xff0c;还容易遗漏那些变体表达和新兴网络…...

EPWM模块影子寄存器的加载机制与应用场景解析

1. EPWM模块影子寄存器基础概念 第一次接触EPWM模块的影子寄存器时&#xff0c;我也被这个"影子"的概念绕晕了。后来在实际项目中调试电机控制才发现&#xff0c;这个机制简直是PWM波形控制的"安全气囊"。简单来说&#xff0c;影子寄存器就是活动寄存器的&…...

魔兽地图跨版本转换与优化全指南:从兼容性处理到地图性能提升

魔兽地图跨版本转换与优化全指南&#xff1a;从兼容性处理到地图性能提升 【免费下载链接】w3x2lni 魔兽地图格式转换工具 项目地址: https://gitcode.com/gh_mirrors/w3/w3x2lni 在魔兽争霸III的地图开发领域&#xff0c;版本兼容性始终是开发者面临的核心挑战。不同游…...

HoRain云--Vue3组件开发:从入门到精通的终极指南

&#x1f3ac; HoRain 云小助手&#xff1a;个人主页 ⛺️生活的理想&#xff0c;就是为了理想的生活! ⛳️ 推荐 前些天发现了一个超棒的服务器购买网站&#xff0c;性价比超高&#xff0c;大内存超划算&#xff01;忍不住分享一下给大家。点击跳转到网站。 目录 ⛳️ 推荐 …...