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

Mybatis 分页查询的三种实现

Mybatis 分页查询

  • 1. 直接在 sql 中使用 limit
  • 2. 使用 RowBounds
  • 3. 使用 Mybatis 提供的拦截器机制
    • 3.1 创建一个自定义拦截器类实现 Interceptor
    • 3.2 创建分页查询函数 与 sql
    • 3.3 编写拦截逻辑
    • 3.4 注册 PageInterceptor 到 Mybatis 拦截器链中
    • 3.5 测试

准备一个分页查询类

@Data
public class Page {// 开始下标 由当前页和每页大小计数而来// 这里也可以是当前页,在sql中进行开始下标的计算private int size;private int currentPage;
}

1. 直接在 sql 中使用 limit

创建一个分页查询函数

List<User> selectUserPage(@Param("page")Page page, @Param("name") String name);

编写sql语句

    <select id="selectUserPage" resultType="com.hzy.demo.pojos.User">select *from user2<where><if test="name != null and name != ''">name like '%${name}%'</if></where><if test="page != null">limit #{page.start},#{page.size}</if></select>

测试

    @Testvoid test08() {int currentPage = 1; // 当前页int size = 2; // 每页大小Page page = new Page();page.setSize(size);page.setStart((currentPage-1)*size);// 第一页 不匹配姓名List<User> users = userMapper.selectUserPage(page, null);for (User user : users){System.out.println(user);}// 第一页 匹配姓名page.setStart((currentPage-1)*size);users = userMapper.selectUserPage(page, "s");for (User user : users){System.out.println(user);}// 第三页 不匹配姓名currentPage = 3;page.setStart((currentPage-1)*size);users = userMapper.selectUserPage(page, null);for (User user : users){System.out.println(user);}}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2. 使用 RowBounds

RowBounds 是 MyBatis 中用于分页查询的一种简单实现方式,它并不涉及数据库分页查询,而是在查询结果返回后进行截取。

RowBounds 的构造函数需要传入两个参数:

  • offset:偏移量,相当于前面的 start

  • limit:限制数量,相当于前面的 size

在这里插入图片描述

RowBounds 的实现原理比较简单,它适用于一些简单的分页需求,但在处理大量数据时可能会导致性能问题,因为所有的数据都会被查询出来,然后在内存中进行截取。对于更复杂的分页需求,可以考虑使用 MyBatis 提供的分页插件或其他更高级的分页方案。

创建查询函数

List<User> selectUserPage(RowBounds rowBounds, @Param("name") String name);

编写 sql

    <select id="selectUserPage" resultType="com.hzy.demo.pojos.User">select *from user2<where><if test="name != null and name != ''">name like '%${name}%'</if></where></select>

测试

    @Testvoid test09() {int currentPage = 1;int size = 2;RowBounds rowBounds = new RowBounds((currentPage - 1) * size, size);List<User> users = userMapper.selectUserPage(rowBounds, null);for (User user : users) {System.out.println(user);}users = userMapper.selectUserPage(rowBounds, "s");for (User user : users) {System.out.println(user);}}

在这里插入图片描述

3. 使用 Mybatis 提供的拦截器机制

MyBatis提供了拦截器(Interceptor)的机制,允许用户在执行SQL语句的过程中进行拦截和干预。拦截器是在执行SQL语句前、后或者代替执行SQL语句的过程中插入自定义的逻辑,从而可以实现一些额外的功能。

一些常见的分页插件比如 PageHelper 也是基于拦截器实现的,这里我们自定义一个拦截器实现分页查询。

3.1 创建一个自定义拦截器类实现 Interceptor

public class PageInterceptor implements Interceptor {//  该方法会在真正的SQL语句执行前后被调用,可以在这里编写拦截逻辑。@Overridepublic Object intercept(Invocation invocation) throws Throwable {return null;}// 用于包装目标对象,返回一个代理对象,该代理对象会拦截目标对象的方法调用。@Overridepublic Object plugin(Object target) {return Interceptor.super.plugin(target);}// 用于设置拦截器的属性,这些属性可以在配置拦截器时传递。@Overridepublic void setProperties(Properties properties) {Interceptor.super.setProperties(properties);}
}

注意要引入 Mybatis 提供的 Interceptor

在这里插入图片描述

3.2 创建分页查询函数 与 sql

查询函数

List<User> selectUserPage(@Param("page") Page page, @Param("name") String name);

sql

    <select id="selectUserPage" resultType="com.hzy.demo.pojos.User">select *from user2<where><if test="name != null and name != ''">name like '%${name}%'</if></where></select>

3.3 编写拦截逻辑

public Object intercept(Invocation invocation) throws Throwable {}

Invocation 接口是 MyBatis 中拦截器机制中的一个核心接口,用于描述拦截的方法调用。Invocation 接口定义了以下方法:

  1. Object getTarget()
    • 获取被拦截的目标对象。在 MyBatis 中,通常是获取到某个 StatementHandler、Executor、ParameterHandler 或 ResultSetHandler 等对象。
  2. Method getMethod()
    • 获取被拦截的目标方法。
  3. Object[] getArgs()
    • 获取被拦截方法的参数。
  4. Object proceed()
    • 调用被拦截方法,相当于执行原始的方法调用。拦截器可以选择是否调用该方法,如果调用,会继续执行原始的方法,如果不调用,可以在拦截器中实现自己的逻辑。

使用 getTarget() 获取目标对象

 StatementHandler statementHandler = (StatementHandler) invocation.getTarget();

StatementHandler 是 MyBatis 中负责处理 SQL 语句的核心接口,它定义了对数据库的操作方法。在 MyBatis 的执行过程中,StatementHandler 负责创建 PreparedStatement 对象、设置参数、执行 SQL 语句等操作。

可以看到 StatementHandler 对象 里面的 boundSql 对象包含了 sql语句 与 方法参数,利用这个就可以实现分页查询。

在这里插入图片描述

拦截逻辑

// @Intercepts 注解配置表明该拦截器会拦截 StatementHandler 接口的 prepare 方法
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class })
})
public class PageInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {StatementHandler statementHandler = (StatementHandler) invocation.getTarget();BoundSql boundSql = statementHandler.getBoundSql();Map parameterObject = (Map)boundSql.getParameterObject();Page page = (Page) parameterObject.getOrDefault("page",null);if (page != null){// 获取原始 SQL 语句String originalSql = boundSql.getSql();// 修改 SQL 语句StringBuilder sb = new StringBuilder();sb.append(originalSql).append(" limit ").append(page.getStart()).append(",").append(page.getSize());// 将修改后的 SQL 设置回 BoundSqlMetaObject metaObject = SystemMetaObject.forObject(boundSql);metaObject.setValue("sql",sb.toString());}// 继续执行 SQL 语句return invocation.proceed();}@Overridepublic Object plugin(Object target) {return Interceptor.super.plugin(target);}@Overridepublic void setProperties(Properties properties) {Interceptor.super.setProperties(properties);}
}

3.4 注册 PageInterceptor 到 Mybatis 拦截器链中

@Configuration
public class MyBatisConfig {@Beanpublic SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();sessionFactory.setDataSource(dataSource);// 添加自定义拦截器Interceptor[] interceptors = new Interceptor[]{new PageInterceptor()};sessionFactory.setPlugins(interceptors);return sessionFactory.getObject();}
}

3.5 测试

    @Testvoid test10() {int currentPage = 1;int size = 4;Page page = new Page();page.setSize(size);page.setStart((currentPage-1)*size);List<User> users = userMapper.selectUserPage(page, null);for (User user : users){System.out.println(user);} }

在这里插入图片描述

相关文章:

Mybatis 分页查询的三种实现

Mybatis 分页查询 1. 直接在 sql 中使用 limit2. 使用 RowBounds3. 使用 Mybatis 提供的拦截器机制3.1 创建一个自定义拦截器类实现 Interceptor3.2 创建分页查询函数 与 sql3.3 编写拦截逻辑3.4 注册 PageInterceptor 到 Mybatis 拦截器链中3.5 测试 准备一个分页查询类 Data…...

各类声音数据集大合集—乐器、车辆、鸟鸣、蜜蜂声音、歌曲、喇叭、人类声音不同等类型的声音数据集

最近收集了一大波关于各类声音的数据集&#xff0c;包含乐器、车辆、鸟鸣、蜜蜂声音、歌曲、喇叭、人类声音不同等类型的声音数据集&#xff0c;废话不多说&#xff0c;给大家逐一介绍&#xff01;&#xff01; 1、吉他和弦大调、小调数据集 吉他和弦大调、小调数据集&#x…...

java设计模式学习之【原型模式】

文章目录 引言原型模式简介定义与用途实现方式UML 使用场景优势与劣势原型模式在spring中的应用员工记录示例代码地址 引言 原型模式是一种创建型设计模式&#xff0c;它允许对象能够复制自身&#xff0c;以此来创建一个新的对象。这种模式在需要重复地创建相似对象时非常有用…...

链表数组插入排序

InsertSort 插入排序算法&#xff0c;比如打扑克牌的算法时&#xff0c;按照从左到右&#xff0c;找到对应的位置插入排序 最重要的是位置移动 找到对应位置值 #include "iostream" #include "bits/stdc.h"using namespace std;void sort(vector<in…...

MyBatis的创建,简单易懂的一篇blog

文章目录 一、MyBatis是什么二、操作流程三.配置resource总结 一、MyBatis是什么 MyBatis 是⼀款优秀的持久层框架&#xff0c;它⽀持⾃定义 SQL、存储过程以及⾼级映射。MyBatis 去除了⼏乎所有的 JDBC 代码以及设置参数和获取结果集的⼯作。MyBatis 可以通过简单的 XML 或注…...

MOS管的静电击穿问题

MOS管输入电阻很高&#xff0c;为什么一遇到静电就不行了&#xff1f; 静电击穿&#xff1a;由于静电的积累导致电压超过了原本MOS的绝缘能力&#xff0c;导致电流突然增大的现象。 MOS管基础知识了解&#xff1a; G极(gate)—栅极&#xff0c;不用说比较好认 S极(source)—源…...

在线 SQL 模拟器SQL Fiddle使用简介

在线 SQL 模拟器SQL Fiddle使用简介 本文可作为“SQL语言与SQL在线实验工具的使用” https://blog.csdn.net/cnds123/article/details/115038700 一文的补充。 有时候&#xff0c;我们想去验证 SQL语句&#xff0c;却缺少数据库环境&#xff0c;那该怎么办呢&#xff1f; 这…...

仿京东淘宝商品列表筛选组件:实现一个高效的侧边栏弹框筛选功能

仿京东淘宝商品列表筛选组件&#xff1a;实现一个高效的侧边栏弹框筛选功能 一、引言 随着电子商务的快速发展&#xff0c;用户体验成为了竞争的关键因素。在众多的电商网站中&#xff0c;如京东和淘宝&#xff0c;商品列表筛选功能为用户提供了便捷的途径来找到心仪的商品。本…...

软件工程 - 第8章 面向对象建模 - 4 - 物理体系结构建模

构件图 构件图概述 构件图描述了软件的各种构件和它们之间的依赖关系。 构件图的作用 在构件图中&#xff0c;系统中的每个物理构件都使用构件符号来表示&#xff0c;通常&#xff0c;构件图看起来像是构件图标的集合&#xff0c;这些图标代表系统中的物理部件&#xff0c;…...

【智能家居】二、添加火灾检测模块(烟雾报警功能点)

可燃气体传感器 MQ-2 和 蜂鸣器 代码段 controlDevice.h&#xff08;设备控制&#xff09;smokeAlarm.c&#xff08;烟雾报警器&#xff09;buzzer.c&#xff08;蜂鸣器&#xff09;mainPro.c&#xff08;主函数&#xff09;运行结果 可燃气体传感器 MQ-2 和 蜂鸣器 代码段 …...

history和hash两种路由模式原理,和优缺点

Hash Hash 模式是在 URL 中使用井号&#xff08;#&#xff09;来作为路由的模式。在 Hash 模式下&#xff0c;即使页面刷新&#xff0c;浏览器仍然只会请求页面的初始 HTML 文件&#xff0c;所有的路由变化都会在 URL 前面添加 “#/” 符号。 原理 在 Hash 模式下&#xff0c;路…...

Nginx 具体应用

1 Nginx 1.1 介绍 一款轻量级的 Web 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器。它占有的内存少&#xff0c;并发能力强&#xff0c;中国大陆使用 nginx 的网站有&#xff1a;百度、京东、新浪、网易、腾讯、淘宝等。第一个公开版本发布于…...

计算机网络之网络传输,三次握手和四次挥手

网络传输通过高低电压 流 基本类型数组 低电压转高电压&#xff0c;通过网卡 传输模式&#xff1a; 全双工&#xff1a;互相传输且能同时传输 半双工&#xff1a;互相传输但是不能同时传输 单工&#xff1a;单向传输&#xff0c;&#xff08;键盘&#xff0c;显示器&#…...

Azure Machine Learning - 在 Azure AI 搜索中创建全文查询

Azure AI搜索中如果要为全文搜索生成查询&#xff0c;本文提供了设置请求的步骤。 本文还介绍了查询结构&#xff0c;并说明了字段属性和语言分析器如何影响查询结果。 关注TechLead&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&a…...

基于YOLOv8深度学习的钢材表面缺陷检测系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…...

深度学习常见回归分支算法逐步分析,各种回归之间的优缺点,适用场景,举例演示

文章目录 1、线性回归&#xff08;Linear Regression&#xff09;1.1 优点1.2 缺点1.3 适用场景1.4 图例说明 2、多项式回归&#xff08;Polynomial Regression&#xff09;2.1 优点2.2 缺点2.3 适用场景2.4 图例说明 3、决策树回归&#xff08;Decision Tree Regression&#…...

Programming Contest 2023(AtCoder Beginner Contest 331)D题 Tile Pattern --- 题解

目录 D - Tile Pattern 题目大意&#xff1a; 思路&#xff1a; 代码&#xff1a; D - Tile Pattern D - Tile Pattern (atcoder.jp) 题目大意&#xff1a; 给你一个n和q&#xff0c;n为局部棋盘大小(n*n) 并且给出局部棋盘中黑白子位置的放置情况&#xff0c;q为查询次数…...

Google测试框架googletest简介与使用方法

环境准备&#xff08;Ubuntu&#xff09; 下载 git clone https://github.com/google/googletest.git 安装 cd googletest // 创建build目录 mkdir build cd build //编译安装 cmake .. make sudo make install 检查是否安装成功 ls /usr/local/lib// 存在以下文件则说明…...

进程的创建:fork()

引入 创建进程的方式我们已经学习了一个&#xff01;在我们运行指令(或者运行我们自己写的可执行程序)的时候不就是创建了一个进程嘛&#xff1f;那个创建进程的方式称为指令级别的创建子进程&#xff01; 那如果我们想要在代码中创建进程该怎么办呢&#xff1f; fork() for…...

Fabric:创建应用通道

搭建自定义网络可以参考文章&#xff1a; https://blog.csdn.net/yeshang_lady/article/details/134113296 1 创建通道 网络搭建完成之后&#xff0c;就可以开始创建通道了。Fabric V2.5.4中可以在不创建系统通道的情况下直接创建应用通道。 1.1 修改配置文件 先创建配置文…...

有了这个Python备忘录,代码拿来即用

这段时间代码写的少了&#xff0c;周末用python写一个小爬虫&#xff0c;却发现连线程的一些方法都不记得了&#xff0c;还得百度查教程。工作越忙&#xff0c;记性越差&#xff0c;发现我疏远了代码&#xff0c;代码也疏远了我。 PS&#xff1a;对于小白来说自学也不是件容易…...

全球不到3%的C++开发者掌握的量子模拟技巧:利用constexpr量子门编译期展开,启动速度提升41倍

第一章&#xff1a;量子计算 C 量子比特模拟示例在经典C环境中模拟量子比特行为&#xff0c;是理解量子门操作与叠加态演化的有效教学手段。本节基于线性代数原理&#xff0c;使用标准C17及以上特性&#xff08;无需外部量子SDK&#xff09;&#xff0c;通过复数向量与酉矩阵实…...

DOCX转LaTeX:从繁琐排版到学术自动化的无缝过渡

DOCX转LaTeX&#xff1a;从繁琐排版到学术自动化的无缝过渡 【免费下载链接】docx2tex Converts Microsoft Word docx to LaTeX 项目地址: https://gitcode.com/gh_mirrors/do/docx2tex 痛点场景&#xff1a;学术写作中的格式转换困境 深夜三点&#xff0c;研究生小李盯…...

基于Cadence 617的带隙基准电压源设计:从理论推导到仿真验证

1. 带隙基准电压源设计基础 第一次接触带隙基准电压源设计时&#xff0c;我被这个看似简单的电路难住了。基准电压源就像电子系统中的"定海神针"&#xff0c;无论温度如何变化&#xff0c;它都能提供稳定的参考电压。在模拟IC设计中&#xff0c;带隙基准(Bandgap Ref…...

成本控制艺术:OpenClaw+Phi-3-vision-128k-instruct任务级计费方案

成本控制艺术&#xff1a;OpenClawPhi-3-vision-128k-instruct任务级计费方案 1. 当Token消耗成为拦路虎 上个月收到账单时&#xff0c;我的手指在鼠标滚轮上停滞了整整三秒——Phi-3-vision-128k-instruct的API调用费用比预期高出47%。这个数字让我意识到&#xff0c;在享受…...

蛋白质结构预测的深度学习之路:从AlphaFold2到ESMFold

点击 “AladdinEdu&#xff0c;你的AI学习实践工作坊”&#xff0c;注册即送-H卡级别算力&#xff0c;沉浸式云原生集成开发环境&#xff0c;80G大显存多卡并行&#xff0c;按量弹性计费&#xff0c;教育用户更享超低价。 摘要&#xff1a;蛋白质结构预测是生命科学的核心难题。…...

踩下油门的那一刻,P2并联混动系统开始了一场精密的能量博弈。咱们今天不聊枯燥的理论,直接钻进Simulink模型里看看这套系统怎么玩转发动机和电机的“二人转

基于Matlab/simulink的P2并联PHEV插电式混合动力汽车建模控制仿真模型&#xff08;同轴、双轴并联插电混合动力汽车仿真模型&#xff09; ——包括整车HCU控制单元、发动机模型、驱动电机模型、AMT5档自动变速箱模型、驾驶员模型、电池能量管理控制模型等&#xff0c;建模详细清…...

产品经理、设计师必看:2026年6款AI界面生成工具实测,哪个最值得用?

过去&#xff0c;一款移动应用从需求文档到可交付原型&#xff0c;至少需要设计师投入 1~2 周时间。而今&#xff0c;借助 AI 界面生成工具&#xff0c;同样的工作可以压缩到几小时甚至几十分钟完成。目前AI界面生成工具正在重塑产品团队的工作方式。本文实测对比了 UXbot、Uiz…...

上市公司数字化转型指数(2007-2024)Word2Vec扩充+TF-IDF

上市公司数字化转型指数&#xff08;2007-2024&#xff09;Word2Vec扩充TF-IDF数据名称&#xff1a;A股上市公司数字化转型指数 时间跨度&#xff1a;2007年-2024年 数据格式&#xff1a;Excel表格&#xff08;dta可直接导入&#xff09; 包含指标&#xff1a;股票代码、年份、…...

STM32CubeMX + EG2131预驱芯片:搞定无刷电机六步换向的硬件配置避坑指南

STM32CubeMX与EG2131预驱芯片的无刷电机六步换向实战解析 引言 在嵌入式电机控制领域&#xff0c;无刷直流电机&#xff08;BLDC&#xff09;因其高效率、长寿命和低维护成本等优势&#xff0c;正逐步取代传统有刷电机。然而&#xff0c;当工程师们从理论转向实践时&#xff0c…...