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);} }

在这里插入图片描述

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

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

相关文章

Clion调试QTQString看不到值问题处理

环境 Clion &#xff1a;2019.3.6 Qt &#xff1a;5.9.6&#xff08;MinGW&#xff09; 环境搭建参考&#xff1a;https://blog.csdn.net/qq_27953479/article/details/132338745 调试时QString看不到值问题处理 下载文件 qt.py : https://github.com/KDE/kdevelop/blob/…

CIS|安森美微光近红外增强相机论文解析

引言 在之前的文章中&#xff0c;我们介绍了索尼、安森美以及三星等Sensor厂家在车载领域中的技术论文&#xff0c;分析了各个厂家不同的技术路线、Sensor架构以及差异点。今天&#xff0c;笔者借豪威科技在移动端200Mega Pixels产品的技术论文&#xff0c;讲解消费级CIS传感器…

如何在WordPress中批量替换图片路径?

很多站长在使用WordPress博客或者搬家时&#xff0c;需要把WordPress文章中的图片路径进行替换来解决图片不显示的问题。总结一下WordPress图片路径批量替换的过程&#xff0c;方便有此类需求的站长们学习。 什么情况下批量替换图片路径 1、更换了网站域名 有许多网站建设初期…

基于SSM的生鲜在线销售系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

亚马逊云科技推出新一代自研芯片

北京——2023 年12月1日 亚马逊云科技在2023 re:Invent全球大会上宣布其自研芯片家族的两个系列推出新一代&#xff0c;包括Amazon Graviton4和Amazon Trainium2&#xff0c;为机器学习&#xff08;ML&#xff09;训练和生成式人工智能&#xff08;AI&#xff09;应用等广泛的工…

锐捷RG-UAC应用网关 前台RCE漏洞复现

0x01 产品简介 锐捷RG-UAC系列应用管理网关是锐捷自主研发的应用管理产品。 0x02 漏洞概述 锐捷RG-UAC应用管理网关 nmc_sync.php 接口处存在命令执行漏洞&#xff0c;未经身份认证的攻击者可执行任意命令控制服务器权限。 0x03 复现环境 FOFA&#xff1a;app"Ruijie-R…

6.8 Windows驱动开发:内核枚举Registry注册表回调

在笔者上一篇文章《内核枚举LoadImage映像回调》中LyShark教大家实现了枚举系统回调中的LoadImage通知消息&#xff0c;本章将实现对Registry注册表通知消息的枚举&#xff0c;与LoadImage消息不同Registry消息不需要解密只要找到CallbackListHead消息回调链表头并解析为_CM_NO…

12-1 Springboot过滤拦截和日志处理

Springboot的日志 默认日志框架&#xff1a;logback 1.日志以文件的形式的保存 使用logback框架 ->(运行日志&#xff0c;开发中用于调式的&#xff0c;在开发中作为系统运行日志记录故障&#xff0c;从而追究问题根源) 2.日志相关的表 记录用户相关操作信息 -> 需要我…

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之linux存储管理(2)》(18)

《Linux操作系统原理分析之linux存储管理&#xff08;1&#xff09;》&#xff08;17&#xff09; 6 Linux存储管理6.2 选段符与段描述符6.2.1 选段符6.2.2 段描述符6.2.3 分段机制的存储保护 6.3 80x86 的分页机制6.3.180x86 的分页机制6.3.2 分页机制的地址转换6.3.3 页表目录…

嵌入式WIFI芯片通过lwip获取心知天气实时天气信息(包含完整代码)

一、天气API 1. 心知天气的产品简介 HyperData 是心知天气的高精度气象数据产品&#xff0c;通过标准的 Restful API 接口&#xff0c;提供标准化的数据访问。无论是 APP、智能硬件还是企业级系统都可以轻松接入心知的精细化天气数据。 HyperData API V4版是当前的最新…

要致富 先撸树——判断循环语句(六)

引子 什么&#xff1f;万年丕更的作者更新了&#xff1f; 没错&#xff01;而且我们不当标题党&#xff0c;我决定把《我的世界》串进文章里。 什么&#xff1f;你不玩《我的世界》&#xff1f; 木有关系 本专栏文章主要在讲c语言的语法点和知识&#xff0c;保证让不玩《我…

Azure Machine Learning - 在 Azure 门户中创建AI搜索技能组

你将了解 Azure AI 搜索中的技能组如何通过添加光学字符识别 (OCR)、图像分析、语言检测、文本翻译和实体识别&#xff0c;在搜索索引中创建可搜索文本的内容。 关注TechLead&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff…

Python程序员入门指南:就业前景

文章目录 标题Python程序员入门指南&#xff1a;就业前景Python 就业数据Python的就业前景SWOT分析法Python 就业分析 标题 Python程序员入门指南&#xff1a;就业前景 Python是一种流行的编程语言&#xff0c;它具有简洁、易读和灵活的特点。Python可以用于多种领域&#xff…

ganache部署智能合约报错VM Exception while processing transaction: invalid opcode

这是因为编译的字节码不正确&#xff0c;ganache和remix编译时需要选择相同的evm version 如下图所示&#xff1a; remix: ganache: 确保两者都选择london或者其他evm&#xff0c;只要确保EVM一致就可以正确编译并部署&#xff0c; 不会再出现VM Exception while processing…

分享一个国内可用的免费GPT4-AI提问AI绘画网站工具

一、前言 ChatGPT GPT4.0&#xff0c;Midjourney绘画&#xff0c;相信对大家应该不感到陌生吧&#xff1f;简单来说&#xff0c;GPT-4技术比之前的GPT-3.5相对来说更加智能&#xff0c;会根据用户的要求生成多种内容甚至也可以和用户进行创作交流。 然而&#xff0c;GPT-4对普…

LangChain 18 LangSmith监控评估Agent并创建对应的数据库

LangChain系列文章 LangChain 实现给动物取名字&#xff0c;LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄LangChain 4用向量数据库Faiss存储&#xff0c;读取YouTube的视频文本搜索I…

SSM框架(五):Maven进阶

文章目录 一、分模块开发1.1 分模块开发的意义1.2 步骤 二、依赖管理2.1 依赖传递2.2 可选依赖和排除依赖 三、继承与聚合3.1 聚合3.2 继承3.3 聚合和继承区别 四、属性4.1 pom文件的依赖使用属性4.2 资源文件使用属性 五、多环境开发六、跳过测试七、私服7.1 下载与使用7.2 私…

文件操作-IO

文件操作-IO 1.认识文件1.什么是文件2.文件路径 2.java中操作文件2.1 File类的用法 3.InputStream和OutputStream的用法 1.认识文件 1.什么是文件 文件是计算机系统中用来存储数据的基本单位。它是一种用于持久性存储数据的命名、有序的数据集合.计算机系统通过文件系统来组织…

gitlab高级功能之容器镜像仓库

今天给大家介绍一个gitlab的高级功能 - Container Registry&#xff0c;该功能可以实现docker镜像的仓库功能&#xff0c;将gitlab上的代码仓的代码通过docker构建后并推入到容器仓库中&#xff0c;好处就是无需再额外部署一套docker仓库。 文章目录 1. 参考文档2. Container R…

Linux 进程(三)

Linux进程状态的查看&#xff1a; 这是Linux内核源代码对于进程状态的定义&#xff1a; R运行状态&#xff08;running&#xff09;: 并不意味着进程一定在运行中&#xff0c;它表明进程要么是在运行中要么在运行队列里。 S睡眠状态&#xff08;sleeping): 意味着进程在…