MybatisPlus分页插件的使用和原理

使用

分页是后端开发的一个基础问题 基本上所有新手都会遇到,从前比较原始的分页 可能需要我们自己写分页 比如拿到分页参数 页数和num,然后自己把它拼接到sql里面去。

MybatisPlus提供了一个分页插件可以很方便的使用 对业务人员比较友好

先给一个简单例子:

    @Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}Spring Boot应用的配置类中,通过@Bean注解配置MyBatis-Plus的分页插件假设有一个User实体类:
public class User {private Long id;private String username;private Integer age;// 省略getter和setter方法
}创建mapper接口
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;@Mapper
public interface UserMapper extends BaseMapper<User> {// 自定义查询方法,例如根据用户名模糊查询List<User> selectByUsername(String username);
}实现
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public List<User> getUserListWithPagination(int pageNum, int pageSize) {// 创建分页对象Page<User> page = new Page<>(pageNum, pageSize);// 执行分页查询,会自动进行分页return userMapper.selectPage(page, null).getRecords();}
}

Page对象表示分页信息,通过调用selectPage()方法执行分页查询,然后通过getRecords()方法获取查询结果。
当我们从前端拿到 pageNum, pageSize 参数的时候 直接用他们创建一个page 对象

然后MybatisPlus拦截器在执行sql的时候 会把带page对象的sql 拦截 加工成分页语句

原理

刚才说了 MybatisPlus拦截器在执行sql的时候 会把带page对象的sql 拦截 加工成分页语句

首先Mybatis会把参数存进 threadlocal 方便同一个线程中 上下文 参数的存取

然后使用拦截器 拦截sql 我们看源码:

  public MybatisPlusInterceptor() {}public Object intercept(Invocation invocation) throws Throwable {Object target = invocation.getTarget();Object[] args = invocation.getArgs();if (target instanceof Executor) {Executor executor = (Executor)target;Object parameter = args[1];boolean isUpdate = args.length == 2;MappedStatement ms = (MappedStatement)args[0];if (!isUpdate && ms.getSqlCommandType() == SqlCommandType.SELECT) {RowBounds rowBounds = (RowBounds)args[2];ResultHandler resultHandler = (ResultHandler)args[3];BoundSql boundSql;if (args.length == 4) {boundSql = ms.getBoundSql(parameter);} else {boundSql = (BoundSql)args[5];}Iterator var11 = this.interceptors.iterator();while(var11.hasNext()) {InnerInterceptor query = (InnerInterceptor)var11.next();if (!query.willDoQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql)) {return Collections.emptyList();}query.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);}CacheKey cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);return executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);}if (isUpdate) {Iterator var8 = this.interceptors.iterator();while(var8.hasNext()) {InnerInterceptor update = (InnerInterceptor)var8.next();if (!update.willDoUpdate(executor, ms, parameter)) {return -1;}update.beforeUpdate(executor, ms, parameter);}}} else {StatementHandler sh = (StatementHandler)target;Connection connections = (Connection)args[0];Integer transactionTimeout = (Integer)args[1];Iterator var16 = this.interceptors.iterator();while(var16.hasNext()) {InnerInterceptor innerInterceptor = (InnerInterceptor)var16.next();innerInterceptor.beforePrepare(sh, connections, transactionTimeout);}}return invocation.proceed();}

看上面的源码

     if (!isUpdate && ms.getSqlCommandType() == SqlCommandType.SELECT) 
这里判断你的sql 是不是select 语句 
如果是那么下面会把sql提取出来BoundSql boundSql;if (args.length == 4) {boundSql = ms.getBoundSql(parameter);} else {boundSql = (BoundSql)args[5];}然后再往下 关键的一步就是 Iterator var11 = this.interceptors.iterator();这里创建nnerInterceptor接口的遍历 InnerInterceptor 的beforeQuery方法 有很多个实现 也就是说有很多个拦截器 这些拦截器 各司其事 有的拦截处理分页 有的拦截处理动态sql 下面就把这些beforeQuery方法的实现类 全部遍历一遍 每次遍历 判断需不需要拦截 如果需要就拦截处理 依次类推 遍历到分页拦截器的时候 发现你的语句中有分页相关参数 就处理分页逻辑 加工sqlwhile(var11.hasNext()) {InnerInterceptor query = (InnerInterceptor)var11.next();if (!query.willDoQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql)) {return Collections.emptyList();}query.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);}CacheKey cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);MyBatis 中,CacheKey 用于标识查询结果的缓存键。它是由当前查询的 MappedStatement、查询参数 parameter、RowBoundsSQL 语句组成的。具体来说,CacheKey 的创建是在执行查询前由 Executor 对象调用 createCacheKey 方法完成的。它的作用是用来检查缓存中是否存在相同查询条件的结果,如果存在,则直接从缓存中获取结果,而不需要再次执行查询。在执行查询时,MyBatis会将当前的 CacheKey 与缓存中已有的键进行比对,如果存在相同的键,则可以直接从缓存中获取查询结果,而不需要再次执行数据库查询操作,从而提高查询效率。return executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);}

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

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

相关文章

代码随想录学习Day 24

93.复原IP地址 题目链接 讲解链接 本题属于切割问题&#xff0c;切割问题需要使用回溯算法来将所有的结果搜索出来&#xff0c;与前一题分割回文串是类似的。本题的树形结构如下图所示&#xff1a; 回溯三部曲&#xff1a; 1.递归函数参数及返回值&#xff1a;参数为待分割…

在 MySQL 某数据表中针对 username 字段建立唯一索引后,基于万级数据量和百万级数据量分别进行查询某用户 A,请问两次查询的性能耗时对比如何?

在 MySQL 数据库中&#xff0c;对 username 字段加了唯一索引后&#xff0c;无论数据量从 1 万增长到 100 万&#xff0c;只要查询条件始终是通过 username 精确查找用户 A&#xff0c;理论上两次查询的耗时应该保持在一个相对稳定的范围内&#xff0c;即查询性能大致保持一致。…

了解监控易(14):中间件监控

在当今的IT运维领域&#xff0c;中间件作为连接应用与底层系统的桥梁&#xff0c;其稳定性和性能至关重要。为了实现高效的一体化运维&#xff0c;各种监控工具应运而生&#xff0c;其中“监控易”以其强大的功能和灵活的适应性&#xff0c;受到了广泛关注。 监控易的核心功能之…

2012年认证杯SPSSPRO杯数学建模D题(第一阶段)人机游戏中的数学模型全过程文档及程序

2012年认证杯SPSSPRO杯数学建模 D题 人机游戏中的数学模型 原题再现&#xff1a; 计算机游戏在社会和生活中享有特殊地位。游戏设计者主要考虑易学性、趣味性和界面友好性。趣味性是本质吸引力&#xff0c;使玩游戏者百玩不厌。网络游戏一般考虑如何搭建安全可靠、丰富多彩的…

JVM高级篇之GC

文章目录 版权声明垃圾回收器的技术演进ShenandoahShenandoah GC体验Shenandoah GC循环过程 ZGCZGC简介ZGC的版本更迭ZGC体验&使用ZGC的参数设置ZGC的调优 版权声明 本博客的内容基于我个人学习黑马程序员课程的学习笔记整理而成。我特此声明&#xff0c;所有版权属于黑马…

MySQL-相关约束

MySQL-约束 前提&#xff1a; 防止数据库中存在不符合语义规定的数据和防止因错误信息的输入输出造成无效操作或错误信息。为了保证数据的完整性&#xff0c;SQL规范以约束的方式对表数据进行额外的条件限制。有以下考虑要点&#xff1a; ①实体完整性&#xff08;Entity In…

【C++】拆分详解 - 内存管理

文章目录 前言一、C/C内存分布二、C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free三、C内存管理方式  3.1 new/delete操作内置类型  3.2 new和delete操作自定义类型  3.3 operator new与operator delete函数 四、new和delete的实现原理  4.1 内置类型…

C++中,`::`

在C中&#xff0c;:: 是作用域解析运算符&#xff08;Scope Resolution Operator&#xff09;。它有以下几种主要的作用&#xff1a; 访问命名空间中的成员&#xff1a;可以使用 :: 来访问命名空间中的变量、函数、类等成员。例如&#xff1a; namespace A {int x 5; }int mai…

【微服务】SpringCloud之Feign远程调用

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 …

Solo 开发者周刊 (第10期):Sora 之后,谁是被遗忘的?谁又是被仰望的?

这里会整合 Solo 社区每周推广内容、产品模块或活动投稿&#xff0c;每周五发布。在这期周刊中&#xff0c;我们将深入探讨开源软件产品的开发旅程&#xff0c;分享来自一线独立开发者的经验和见解。本杂志开源&#xff0c;欢迎投稿。 好文推荐 Solo 社区 x 机器之心-再谈复现 …

如何利用HubSpot 出海CRM实现精准海外客户定位与拓展?

在当今全球化的商业环境中&#xff0c;企业寻求海外市场的拓展已成为增长的重要策略。然而&#xff0c;海外市场的复杂性和多样性为企业带来了巨大的挑战。为了有效地定位和拓展海外客户&#xff0c;许多企业选择了HubSpot 出海CRM作为他们的营销和销售管理工具。今天运营坛将带…

Android Glide

1.引入glide implementation com.github.bumptech.glide:glide:4.14.2 // Skip this if you dont want to use integration libraries or configure Glide. annotationProcessor com.github.bumptech.glide:compiler:4.14.2 //Glide 注解处理器 2.AndroidManifest.xml 中添加…

HarmonyOS NEXT应用开发之LocalStorage:页面级UI状态存储

LocalStorage是页面级的UI状态存储&#xff0c;通过Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例内多个页面间状态共享。 本文仅介绍LocalStorage使用场景和相关的装饰器&#xff1a;LocalStorageProp和LocalStorageLink。 说…

购买代码签名证书时需提供哪些认证资料?

在软件开发与发布过程中&#xff0c;确保软件的可靠性和完整性至关重要&#xff0c;为此购买代码签名证书是必不可少的环节。然而&#xff0c;许多开发者对于购买该证书所需的具体材料并不十分清楚。下面就为大家详细介绍购买代码签名证书所需材料&#xff0c;助您更好地筹备和…

文心一言指令词宝典之自媒体篇

作者&#xff1a;哈哥撩编程&#xff08;视频号、抖音、公众号同名&#xff09; 新星计划全栈领域优秀创作者博客专家全国博客之星第四名超级个体COC上海社区主理人特约讲师谷歌亚马逊演讲嘉宾科技博主极星会首批签约作者 &#x1f3c6; 推荐专栏&#xff1a; &#x1f3c5;…

考研||考公||就业||其他?-------愿不再犹豫

大三下了&#xff0c;现在已经开学一个多月了&#xff0c;在上个学期的时候陆陆续续吧周围有的行动早的人已经开始准备考研了&#xff0c;当然这只是下小部分人吧&#xff0c;也有一部分人是寒假可能就开始了&#xff0c;更多的则是开学的时候&#xff0c;我的直观感受是图书馆…

【Easy云盘 | 第二篇】后端统一设计思想

文章目录 4.1后端统一设计思想4.1.1后端统一返回格式对象4.1.2后端统一响应状态码4.1.3后端统一异常处理类4.1.4StringUtils类4.1.5 RedisUtils类 4.1后端统一设计思想 4.1.1后端统一返回格式对象 com.easypan.entity.vo.ResponseVO Data public class ResponseVO<T> …

Sharding

Sharding操作 什么是ShardingSharding-JDBC一、引入maven依赖 &#xff08;sharding-jdbc-spring-boot-starter&#xff09;二、水平分表操作&#xff08;一个库多个相同结构表&#xff09;其他的maven依赖版本 &#xff08;shardingsphere-jdbc-core-spring-boot-starter&…

鸿蒙:应用级变量的状态管理

状态管理模块提供了应用程序的数据存储能力、持久化数据管理能力、UIAbility数据存储能力和应用程序需要的环境状态。 说明 本模块首批接口从API version 7开始支持&#xff0c;后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 本文中T和S的含义如下&…

【翻译】F - Max Sum Counting Editorial by en_translator

给定两个序列 A 和 B&#xff0c;按照 A_i 的增序对它们进行排序&#xff08;如果 A_i 相等&#xff0c;则按照 B_i 来确定顺序&#xff09;。对于集合 {1, 2, ..., N} 的每个非空子集 S&#xff0c;满足 max_{i∈S} A_i A_{max(S)}。因此&#xff0c;我们可以将问题转化如下。…