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传感器…

高级软件工程15本书籍

如果您想学习软件工程技能并提高您的专业知识&#xff0c;那么这里是您的最佳选择。我们有一本很棒的书&#xff0c;可以极大地增强您在软件工程方面的知识。 1&#xff09;干净的代码 Robert C. Martin 写了一本名为“干净代码&#xff1a;敏捷软件工艺手册”的书。在本书中&…

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

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

面试 Java 基础八股文十问十答第二期

面试 Java 基础八股文十问十答第二期 作者&#xff1a;程序员小白条 ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 11.什么是反射&#xff1f;反射有哪些作用&#xff1f;反射在Sping中的体现 (1): 什么是反射? 反射可以在运行时获取到一个类的所有信息&#xff0c;包括(成员变量&am…

关于qiankun沙箱sandbox(面试题)

为什么要有js资源隔离机制&#xff1f; 主应用和子应用&#xff0c;相同的全局变量&#xff0c;可能会发生冲突&#xff0c;子应用和子应用之间&#xff0c;相同的全局变量&#xff0c;也可能会发生冲突。在这里我们主要指的就是window。 思路&#xff1a;打开沙箱时能够修改…

Spring中@Transactional注解

在Spring框架中&#xff0c;Transactional 是一个注解&#xff0c;用于声明事务性的方法。这个注解可以被应用在方法级别或类级别上。它提供了一种声明式的事务管理方式&#xff0c;避免了在代码中直接编写事务管理相关的代码。Transactional 注解能够将一个方法纳入到一个事务…

基于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;应用等广泛的工…

Linux: 退出vim编辑模式

一、使用快捷键进行退出 1、按“Esc”键进入命令模式 当我们在vim编辑模式下输入完毕需要进行退出操作时&#xff0c;首先需要按下“Esc”键&#xff0c;将vim编辑器从插入模式或者替换模式切换到命令模式。 ESC 2、输入“:wq”保存并退出 在命令模式下&#xff0c;输入“:…

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

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

JavaWeb | JavaScript基础

目录: 1.JavaScript简介2.JavaScript注释3.JavaScript语法 :变量的定义函数的定义 4.JavaScript内置对象4.1 window的作用 &#xff1a;出现提示框打开关闭窗口定时器 4.2 history的作用4.3 document的作用 &#xff1a;在网页上输出设置网页属性访问文档元素&#xff0c;特别是…

jni子线程回调java实例

背景 最近有项目需求&#xff0c;需要在jni中创建多个子线程&#xff0c;并在子线程中&#xff0c;回调java将byte[]数据上报给java处理 demo实例 关键代码 static jmethodID method_callback; jclass global_class NULL; jclass myClass NULL; JavaVM* gJavaVM NULL;ji…

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

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

基于Java SSM人才市场管理系统

随着人才流动的正常化以及大专院校毕业生就业人数的增长&#xff0c;人才市场的业务越来越红火。人才市场管理系统实现对人才市场业务的规范化管理。系统主要管理的信息及操作如下&#xff1a; 用人单位&#xff1a;编号、名称、联系人、电话、招聘人数、学历要求、职称要求。 …

【Java面试——基础题】

Java基础部分&#xff0c;包括语法基础&#xff0c;泛型&#xff0c;注解&#xff0c;异常&#xff0c;反射和其它&#xff08;如SPI机制等&#xff09;。 1.1 语法基础 面向对象特性&#xff1f; 封装 利用抽象数据类型将数据和基于数据的操作封装在一起&#xff0c;使其构成…

kubelet漏洞CVE-2020-8559复现与分析

首先下载源码 git clone --branch v1.17.1 --single-branch https://github.com/kubernetes/kubernetes.git 参考 移花接木&#xff1a;看CVE-2020-8559如何逆袭获取集群权限-腾讯云开发者社区-腾讯云

React Router(用法介绍)

React Router 是一个用于在 React 应用中处理路由的库。它允许你定义应用程序中的多个页面&#xff0c;并在 URL 改变时显示不同的内容。 要使用 React Router&#xff0c;你需要首先安装它&#xff1a; npm install react-router-dom然后&#xff0c;在你的应用中引入所需的…

一些小笔记(Delphi)

工具&#xff1a;Delphi10.4 用Delphi写了一个解析json文件的小程序&#xff0c; 需求是能解析整个文件夹中的所有文件&#xff0c;也能只解析某一个文件&#xff0c;文件或者文件夹的路径能够直接填写&#xff0c;也能够通过选择的方式去填充。 我的解决办法如下&#xff1…

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

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