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环境中配置方式如下: /*** author giserDev* description 配置分页插件、方言、mapper包扫描等* date 2023-12-13 …...

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

3D摄影棚布光:Set A Light 3D Studio
Set A Light 3D Studio是一款专业的灯光模拟软件,旨在帮助摄影师和电影制片人在电脑上进行虚拟灯光布置和场景模拟,以实现更加精准和高质量的拍摄效果。该软件提供了丰富的灯光和场景模型,支持灵活调整光源位置、强度、颜色和效果等参数&…...
#HarmonyOS:应用的包名配置--应用图标和标签配置--配置链接
配置相关 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/application-component-configuration-stage-0000001478340869-V2 应用的包名配置 应用需要在工程的AppScope目录下的app.json5配置文件中配置bundleName标签,该标签用于标识应用的唯…...

docker小白第三天
docker小白第三天 docker为什么会比虚拟机快 1、docker有着比虚拟机更少的抽象层。不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源,因此在CPU、内存利用率上docker将会在效率上有明显优势。 2、dock…...
FFmpegd的AVBSF
本章主要介绍AVBSF 文章目录 结构体定义对外函数常见的过滤器 从名字我们可以知道这是个码流过滤器,我们最常用的是一个叫做h264_mp4toannexb_bsf的东东 这个过滤器的作用是把h264以MP4格式的NALU转换为annexb(0x000001) const AVBitStreamF…...

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

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

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

【JVM从入门到实战】(六)类加载器的双亲委派机制
一、双亲委派机制 在Java中如何使用代码的方式去主动加载一个类呢? 方式1:使用Class.forName方法,使用当前类的类加载器去加载指定的类。 方式2:获取到类加载器,通过类加载器的loadClass方法指定某个类加载器加载。 …...

SpringCloud面试题及答案(最新50道大厂版,持续更新)
在Java开发中,Spring Cloud作为微服务架构的关键组成部分,为了帮助广大Java技术爱好者和专业开发人员深入理解Spring Cloud,本文《SpringCloud面试题及答案(最新50道大厂版,持续更新)》提供了最前沿、最实用…...
Next.js 的设计理念
Next.js 的设计理念:简洁、强大与高效 Next.js 是一个流行的 React 框架,由 Vercel 公司开发。它的设计理念是简洁、强大和高效,这种理念贯穿于 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 :主配置文件,配置 ansible…...

Stable Diffusion 源码解析(1)
参考1:https://blog.csdn.net/Eric_1993/article/details/129393890 参考2: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进行用户登录时出现的问题,因为jdk版本太高导致的 解决办法: 方法一: 降低jdk版本 检查JDK版本,如果你是JDK17版本,就降到JDK8版本 方案二:在meven中添加依赖 注意: 如果2.3.1的版本不生效,则使用2.3.0的版本 <…...

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

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

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

一键提取微信聊天记录,生成HTML、Word文档永久保存,还能生成微信年度聊天报告
不知道生活中你有没有遇到过这种情况,聊天记录不完整,有的在手机上,有的在电脑上,搜索起来很烦。那有没有一种办法可以把微信聊天记录统一呢?当然是有的。下面,就让我们一起来看一下怎么操作。 先看效果 操…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...