mybatis开发一个分页插件、mybatis实现分页、mybatis拦截器

mybatis开发一个分页插件、mybatis实现分页、mybatis拦截器

通过官网的mybatis插件说明可知,我们可以通过拦截器进行开发一个插件。

例如这样的:

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);// 开始分页MagicPage.startPage(1, 3);// 查询List<UserEntity> list = mapper.selectAll();System.out.println(list);// 获取到分页的内容PageInfo page = MagicPage.getPage();System.out.println(page);

格式就是通过线程变量来实现

MagicPage.start(page,size);
// 执行查询
...
MagicPage.getPage();

先编写一个 MagicPage

import cn.hutool.core.lang.Assert;/*** @author lingkang* Created by 2024/3/3*/
public class MagicPage {private static final ThreadLocal<PageInfo> local = new ThreadLocal<>();/*** 开始分页** @param page 默认 1* @param size 默认 10*/public static void startPage(int page, int size) {Assert.isTrue(page > 0, "page 最小值为 1");Assert.isTrue(size > 0, "size 必须大于 0");PageInfo info = new PageInfo();info.setSize(size);info.setPage(page);local.set(info);}public static PageInfo getPage() {return local.get();}public static void removePage() {local.remove();}
}

PageInfo

@Data
public class PageInfo {private int size;private int page;private long total;
}

mybatis插件实现:

import cn.hutool.core.convert.BasicType;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** 查询分页拦截** @author lingkang* Created by 2024/3/3*/
@Intercepts({@Signature(type = StatementHandler.class,method = "prepare",args = {Connection.class, Integer.class})})
public class MagicPageInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {PageInfo page = MagicPage.getPage();if (page == null)return invocation.proceed();StatementHandler statementHandler = (StatementHandler) invocation.getTarget();BoundSql boundSql = statementHandler.getBoundSql();if (!boundSql.getSql().toLowerCase().contains("select")) {return invocation.proceed();}Connection conn = (Connection) invocation.getArgs()[0];String totalSql = "select count(*) ";TotalConvert convert = pageSql(boundSql.getSql());if (convert.getOrderIndex() != 0)totalSql += boundSql.getSql().substring(convert.getTotalIndex()) + boundSql.getSql().substring(convert.getOrderIndex());elsetotalSql += boundSql.getSql().substring(convert.getTotalIndex());PreparedStatement statement = conn.prepareStatement(totalSql);Object parameterObject = boundSql.getParameterObject();// 设置参数if (parameterObject != null) {if (parameterObject.getClass().isPrimitive() || BasicType.WRAPPER_PRIMITIVE_MAP.containsKey(parameterObject.getClass())) {statement.setObject(1, parameterObject);} else if (parameterObject.getClass().isArray()) {Object[] arr = (Object[]) parameterObject;for (int i = 1; i <= arr.length; i++)statement.setObject(i, arr[i]);} else if (parameterObject instanceof Collection) {int i = 1;for (Object o : (Collection) parameterObject)statement.setObject(i++, o);} else if (parameterObject instanceof Map) {Map map = (Map) parameterObject;int i = 1;for (ParameterMapping mapping : boundSql.getParameterMappings())statement.setObject(i++, map.get(mapping.getProperty()));} else {// 将它当成对象int i = 1;for (ParameterMapping mapping : boundSql.getParameterMappings()) {Field field = parameterObject.getClass().getDeclaredField(mapping.getProperty());field.setAccessible(true);statement.setObject(i++, field.get(parameterObject));}}}ResultSet resultSet = statement.executeQuery();if (resultSet.next()) {long total = resultSet.getLong(1);page.setTotal(total);resultSet.close();}if (page.getTotal() > 0) {// 存在分页String sql = boundSql.getSql() + " limit " + (page.getPage() - 1) * page.getSize() + "," + page.getSize();Field field = BoundSql.class.getDeclaredField("sql");field.setAccessible(true);field.set(boundSql, sql);}return invocation.proceed();}Pattern orderBy = Pattern.compile("order\\s+by");/*** select id,(select username from user where id=t_order.userid) as username from t_order order by id desc*/private TotalConvert pageSql(String sql) {TotalConvert convert = new TotalConvert();sql = sql.toLowerCase();int index = sql.indexOf("from");int start = sql.substring(0, index).indexOf("(");while (start != -1) {start = sql.indexOf("(", start + 1);if (start == -1)index = sql.indexOf("from", index + 1);}convert.setTotalIndex(index);// 匹配排序,可能存在排序,需要特殊处理Matcher matcher = orderBy.matcher(sql);if (matcher.find()) {convert.setOrderIndex(matcher.start());}return convert;}
}

需要注意,上面的插件只是做了mysql语法下的分页,如果是sqlserver以及其他数据库需要做调整

配置我们的插件

// 将拦截器添加到配置
configuration.addInterceptor(new MagicPageInterceptor());

执行效果:
在这里插入图片描述

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

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

相关文章

Linux:线程的概念

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》《C》《Linux》 文章目录 前言一、线程的概念线程代码的简单示例 总结 前言 本文是对于线程概念的知识总结 一、线程的概念 在课本上&#xff0c;线程是比进程更轻量级的一种指向流 或 线程是在…

VS Code 的粘性滚动预览 - 类似于 Excel 的冻结首行

VS Code 的粘性滚动预览 - 类似于 Excel 的冻结首行功能&#xff0c;即滚动 UI 显示当前源代码范围。便于在代码行数比较多的时候更好的知道自己所在的位置。粘性滚动UI 显示用户在滚动期间所处的范围&#xff0c;将显示编辑器顶部所在的类/接口/命名空间/函数/方法/构造函数&a…

理解这几个安全漏洞,你也能做安全测试

01 短信炸弹 1、漏洞描述 短信轰炸攻击是常见的一种攻击&#xff0c;攻击者通过网站页面中所提供的发送短信验证码的功能处&#xff0c;通过对其发送数据包的获取后&#xff0c;进行重放&#xff0c;如果服务器短信平台未做校验的情况时&#xff0c;系统会一直去发送短信&…

JVM内部世界(内存划分,类加载,垃圾回收)

&#x1f495;"Echo"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;JVM内部世界(内存划分,类加载,垃圾回收) 关于JVM的学习主要掌握三方面: JVM内存区的划分类加载垃圾回收 一.JVM内存区的划分 当一个Java进程开始执行时,JVM会首先向操作系统申…

实例驱动计算机网络

文章目录 计算机网络的层次结构应用层DNSHTTP协议HTTP请求响应过程 运输层TCP协议TCP协议面向连接实现TCP的三次握手连接TCP的四次挥手断开连接 TCP协议可靠性实现TCP的流量控制TCP的拥塞控制TCP的重传机制 UDP协议 网际层IP协议&#xff08;主机与主机&#xff09;IP地址的分类…

【创作回顾】17个月峥嵘创作史

#里程碑专区#、#创作者纪念日# 还记得 2022 年 10 月 05 日&#xff0c;我在CSDN撰写了第 1 篇博客——《关于测试工程师瓶颈和突围的一个思考》&#xff0c;也是我在全网发布的第一篇技术文章。 回想当时&#xff0c;这一篇的诞生过程并不轻松&#xff0c;不像是一篇网络文章…

【计算机网络】深度学习HTTPS协议

&#x1f493; 博客主页&#xff1a;从零开始的-CodeNinja之路 ⏩ 收录文章&#xff1a;【计算机网络】深度学习HTTPS协议 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 一:HTTPS是什么二:HTTPS的工作过程三:对称加密四:非对称加密五:中间人攻击1…

【web | CTF】BUUCTF [HCTF 2018]WarmUp

天命&#xff1a;这题本地php代码是无法复现的 首先打开网站&#xff0c;啥也没有&#xff0c;查看源码 发现文件&#xff0c;打开访问一下看看&#xff0c;发现是代码审计 <?phphighlight_file(__FILE__);class emmm{public static function checkFile(&$page){$whit…

【学习总结】什么是DoS和DDoS

[Q&A] 什么是DoS DoS 是 “Denial of Service”&#xff08;拒绝服务&#xff09;的缩写&#xff0c;它是一种网络攻击方式&#xff0c;其目的是使目标计算机或网络资源无法为合法用户提供正常的服务。通过向目标系统发送大量请求、消耗其带宽、处理器或内存等资源&#…

13 双口 RAM IP 核

双口 RAM IP 核简介 双口 RAM IP 核有两个端口&#xff0c;它又分为伪双端口 RAM 和真双端口 RAM&#xff0c;伪双端口 RAM 一个端口只能读&#xff0c;另一个端口只能 写&#xff0c;真双端口 RAM 两个端口都可以进行读写操作。同时对存储器进行读写操作时就会用到双端口 RAM…

unity-1

创建游戏对象&#xff08;游戏物体&#xff09; 可通过unity中的菜单栏中的Gameobject创建&#xff1b;也可在Hierarchy&#xff08;层级&#xff09;中创建&#xff0c; 双击即可居中看到。 在Hierarchy空白处右键即可看到&#xff0c;能创建游戏对象。 在Scene框中&#x…

BioTech - ADMET的性质预测 概述

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/136438192 ADMET&#xff0c;即 Absorption、Distribution、Metabolism、Excretion、Toxicity&#xff0c;吸收、分布、代谢、排泄、毒性…

Linux shell:补充命令的使用

目录 一.导读 二.正文 三.结语 一.导读 上一篇介绍了脚本的简单概念以及使用&#xff0c;现在补充一些命令。 二.正文 目前处于全局目录&#xff0c;通过mkdir创建名我为day01的文件。 通过cd命令day01 切换至day01文件当中。 使用vim文本编辑器文件名&#xff08;firstdir&…

【Python】进阶学习:pandas--query()用法详解

&#x1f4da;【Python】进阶学习&#xff1a;pandas–query()用法详解 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希…

LeetCode --- 无重复字符的最长子串

题目描述 无重复字符的最长子串 找到无重复的最长连续字符串。 示例1中 abc | bca | cab 都符合题意。输出3即可。 代码 可以使用暴力枚举 哈希表&#xff0c;哈希表来判断是否重复&#xff0c;枚举来判断每一种情况&#xff0c;需要开两层for循环&#xff0c;时间复杂度n…

linux高级编程:线程(二)、进程间的通信方式

线程&#xff1a; 回顾线程&#xff08;一&#xff09;&#xff1a; 1.线程间通信问题 线程间共享同一个资源&#xff08;临界资源&#xff09; 互斥&#xff1a; 排他性访问 linux系统 -- 提供了Posix标准的函数库 -- 互斥量&#xff08;互斥锁&#xff09; 原子操作&#x…

Bililive-go 实现直播自动监控录制

前言 最近有直播录制的需求&#xff0c;但是自己手动录制太麻烦繁琐&#xff0c;于是用了开源项目Bililive-go进行全自动监控录制&#xff0c;目前这个项目已经有3K stars了 部署 为了方便我使用了docker compose 部署 version: 3.8 services:bililive:image: chigusa/bilil…

javascript实现的星座查询

今天在这个网站http://xzxys.wiicha.com/看到查询星座幸运色的效果&#xff0c;想研究一下代码&#xff0c;结果右键禁用。后来参考了一下别人的代码&#xff0c;琢磨着先实现了一下星座查询的功能&#xff0c;输入月份和日期四位数后&#xff0c;可以查询属于哪个星座&#xf…

群体风暴之锤(War3地图编辑器)

文章目录 0、大致原理1、创建隐形单位2、新事件开端3、环境→新条件4、动作4.1、单位组4.1.1、圆范围内单位4.1.2、指定条件 4.2、对单位组内的所有单位释放风暴之锤 0、大致原理 真MK向目标点释放风暴之锤时选定&#xff08;以技能释放点为圆心&#xff0c;设定半径&#xff0…

Python编程语言常用的包管理工具介绍

conda是一个开源的包管理器和环境管理器&#xff0c;用于安装、运行和更新包和它们的依赖项。conda可以用于Python编程语言&#xff0c;但它也支持其他编程语言。conda的主要特点是它能够在不同的环境中管理不同的包集合&#xff0c;这使得它非常适合于数据科学和机器学习项目&…