当前位置: 首页 > 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 修改配置文件 先创建配置文…...

力扣每日一题(2023-11-30)

力扣每日一题 题目&#xff1a;1657. 确定两个字符串是否接近 日期&#xff1a;2023-11-30 用时&#xff1a;21 m 07 s 时间&#xff1a;11ms 内存&#xff1a;43.70MB 代码&#xff1a; class Solution {public boolean closeStrings(String word1, String word2) {if(word1.…...

内部类Lambda

静态内部类 /*** 静态成员是在类加载成字节码时就已经存在的,静态只能访问静态*/ public class Demo {public static void main(String[] args) {Outer.Inner.show();} }class Outer {int num1 10;static int num2 20;static class Inner {static void show() {Outer outer …...

设一棵二叉树中各结点的值互不相同,其先序遍历序列和中序遍历序列分别存于两个一维数组A[1...n]和 Bfl...n]中,试编写算法建立该二叉树的二叉链表。

题目描述&#xff1a;设一棵二叉树中各结点的值互不相同&#xff0c;其先序遍历序列和中序遍历序列分别存于两个一维数组A[1…n]和 B[1…n]中&#xff0c;试编写算法建立该二叉树的二叉链表。 分析&#xff1a; 对于一颗二叉树&#xff0c;知道其中序和先序序列就可以完全确定…...

什么是Daily Scrum?

Daily Scrum&#xff08;每日站会&#xff09;&#xff0c;Scrum Master要确保这个会在每天都会开。这个会的目的就是检查正在做的东西和方式是否有利于完成Sprint目的&#xff0c;并及时做出必要的调整。 每日站会一般只开15分钟&#xff0c;为了让事情更简单些&#xff0c;这…...

逆波兰表达式求值[中等]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给你一个字符串数组tokens&#xff0c;表示一个根据 逆波兰表示法 表示的算术表达式。请你计算该表达式。返回一个表示表达式值的整数。 有效的算符为 ‘’、‘-’、‘*’ 和 ‘/’ 。 每个操作数&#xff08;运算对象&#xff09;都…...

Oracle连接和使用

5. Oracle连接和使用 5.1. sqlplus sqlplus作为甲骨文公司提供的一款本族工具产品,有着悠久的历史和积淀,它几乎伴随着Oracle数据库产生至今的整个生命周期,而且,还会继续和Oracle数据库产品相伴一直发展下去。该工具看似简单灵活的背后,却为广大用户使用Oracle数据库提…...

redis单线程为什么这么快

redis单线程为什么这么快 redis是使用的单线程来进行操作的&#xff0c;因为所有的数据都是在内存中的&#xff0c;内存操作特别快。而且单线程避免了多线程切换性能损耗问题 单线程如何处理并发客户端连接&#xff1f; redis利用epoll来实现IO多路复用&#xff0c;将连接信息和…...

工业机器视觉megauging(向光有光)使用说明书(五,轻量级的visionpro)

这个说明主要介绍抓线功能。 第一步&#xff0c;添加线工具&#xff0c;鼠标双击工具箱“抓线”&#xff0c;出现如下界面&#xff1a; 第二步&#xff0c;我们拉一条&#xff0c;“九点标定”到“抓线1”的线&#xff0c;和visionpro操作一样&#xff1a; 第三步&#xff0c;…...

【LittleXi】2023年广东工业大学腾讯杯新生程序设计竞赛

文章目录 【LittleXi】2023年广东工业大学腾讯杯新生程序设计竞赛A.星期几考试&#xff1f;C.信件D、乘除法E、不知道叫什么名字F.我要学会盾反&#xff01;G.闪闪发光心动不已&#xff01;H.不想想背景的gcdI.uu爱玩飞行棋J.火柴人小游戏K .有趣的BOSS 【LittleXi】2023年广东…...

【C语言:数据在内存中的存储】

文章目录 1.整数在内存中的存储1.1整数在内存中的存储1.2整型提升 2.大小端字节序2.1什么是大小端2.2为什么有大小端之分 3.整数在内存中的存储相关题目题目一题目二题目三题目四题目五题目六题目七 4.浮点数在内存中的存储4.1浮点数存的过程4.2浮点数取得过程 在这之前呢&…...