mybatis 实现查询默认添加分页

前言

        分页查询在日常开发中无法避免,但每次sql编写时,mybatis 中使用limit,oracle中使用rownum分页,业务场景少的情况下,可以接受.但是随着业务增加每次相同的功能做重复开发又不是那么方便,那么我们有什么方案去解决开发中出现的分页问题呢?

一、PageHelper 框架分页

首先我们看下pageHelper框架的分页核心类PageInterceptor 同样是实现了mybatis的Interceptor

                

二、自定义实现mybatis 插件 Interceptor (与pageHelper类似)

  •    当涉及系统中的查询语句,参数为RowBounds时,查询语句会默认根据RowBounds分页

package com.cloud.common;import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.builder.StaticSqlSource;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Properties;/*** @author haizhuangbu* @date 2022/6/5 18:25* @mark MybatisIntercepter mybatis 拦截器*/
@Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))
@Slf4j
public class MybatisInterceptor implements Interceptor {private Logger logger = LoggerFactory.getLogger(MybatisInterceptor.class);private final Integer MAPPED_STATEMENT_INDEX = 0;private final Integer PARAM = 1;// 默认分页private final Integer ROW_BOUNDS_INDEX = 2;@Overridepublic Object intercept(Invocation invocation) throws Throwable {logger.info("分页拦截器");// 1. 方法获取参数Object[] args = invocation.getArgs();// 分页器RowBounds rowBounds = (RowBounds) args[ROW_BOUNDS_INDEX];// 检查是否为默认分页if (rowBounds == RowBounds.DEFAULT) {return invocation.proceed();}// 设置为默认args[ROW_BOUNDS_INDEX] = RowBounds.DEFAULT;// 执行器MappedStatement mappedStatements = (MappedStatement) args[MAPPED_STATEMENT_INDEX];// 获取执行sqlBoundSql boundSql = mappedStatements.getBoundSql(PARAM);String sql = boundSql.getSql();// 获取数据库类型String databaseProductName = mappedStatements.getConfiguration().getEnvironment().getDataSource().getConnection().getMetaData().getDatabaseProductName();// mysql 的 分页处理if ("MYSQL".equalsIgnoreCase(databaseProductName)) {sql = mysql(sql, rowBounds);}// oracle 的分页处理if ("ORACLE".equalsIgnoreCase(databaseProductName)) {sql = oracle(sql, rowBounds);}logger.info("sql:{}", sql);StaticSqlSource staticSqlSource = new StaticSqlSource(mappedStatements.getConfiguration(), sql, boundSql.getParameterMappings());// 通过反射设置MapperStatment 的sqlSource字段Field field = MappedStatement.class.getDeclaredField("sqlSource");field.setAccessible(true);field.set(mappedStatements, staticSqlSource);return invocation.proceed();}private String oracle(String sql, RowBounds rowBounds) {// 为查询语句给到别名sql = "select * from (select t1.*, rownum rn from (" + sql +") t1 ) t2 where rn > " + (rowBounds.getOffset() - 1) * rowBounds.getLimit() + " and rn <= " + rowBounds.getOffset() * rowBounds.getLimit();return sql;}private String mysql(String sql, RowBounds rowBounds) {// 页数int limit = rowBounds.getLimit();// 页码int offset = rowBounds.getOffset();String format = String.format("LIMIT %d,%d", offset, limit);if (sql.contains(format)) {
//            sql = sql.replaceAll("select", "SELECT COUNT(1) total,");sql = sql.replaceAll(format, "");}sql += " " + format;return sql;}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {Interceptor.super.setProperties(properties);}}
  • 将自定义插件交给spring

@Beanpublic ConfigurationCustomizer configurationCustomizer() {return new ConfigurationCustomizer() {@Overridepublic void customize(Configuration configuration) {configuration.addInterceptor(new MybatisInterceptor());}};}

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

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

相关文章

温酒读Qt:QObject中篇2 ——欲遮还羞的 QObjectPrivate

《妙法莲华经》曰&#xff1a;“佛道长远&#xff0c;久受勤苦&#xff0c;乃可得成。” 世事修炼&#xff0c;莫不如是&#xff0c;日拱一卒无有尽&#xff0c;功不唐捐终入海。 传送门: 《温酒读Qt&#xff1a;QObject 序篇》 《温酒读Qt&#xff1a;QObject中篇1—— Q_OBJ…

Neo4j在java中的使用

1.Neo4j访问的两种方式 嵌入式数据库服务器模式(通过REST的访问) 它是由应用程序的性质&#xff08;neo4j是独立服务器 还是和程序在一起),性能&#xff0c;监控和数据安全性来决定架构选择。 An embedded database&#xff08;嵌入式数据库&#xff09; 嵌入式Neo4j数据库…

前端框架---Vue2学习教程(上)

从HTML到现在一路跟过来的小伙伴们&#xff0c;坚持固然不容易&#xff0c;但我相信大家已经学到了不少&#xff0c;那么我们开始马不停蹄的进入前端的框架吧&#xff0c;下面讲的是Vue2&#xff0c;大家继续加油鸭&#xff01;&#xff01;&#xff01;&#xff01; Vue2 Vu…

装机打不开BIOS怎么办?如何进入Windows10的BIOS页面,如何关闭快速启动

电脑有快速启动&#xff0c;想进去BIOS页面非常困难&#xff0c;在临开机的页面&#xff0c;按触发按键不管用。 然后我看到了一种新的进入BIOS的方式&#xff1a; &#xff08;1&#xff09;win8以上的系统&#xff0c;按住shift&#xff0c;然后鼠标点击重启&#xff0c;再…

代码随想录算法训练营第34天(贪心算法03● 1005.K次取反后最大化的数组和 ● 134. 加油站 ● 135. 分发糖果

贪心算法 part03 1005.K次取反后最大化的数组和解题思路 134. 加油站解题思路注意点 135. 分发糖果解题思路 1005.K次取反后最大化的数组和 本题简单一些&#xff0c;估计大家不用想着贪心 &#xff0c;用自己直觉也会有思路。 题目链接&#xff1a; 1005.K次取反后最大化的数组…

蓝桥杯2024/1/26笔记-----基于PCF8591的电压采集装置

功能实现要求&#xff1a; 每次建好工程文件夹&#xff0c;里边包含User&#xff08;放工程文件&#xff0c;mian.c&#xff0c;可以在这里写如同我这个文章的文本文档&#xff09;、Driver&#xff08;存放底层文件如Led.c&#xff0c;Led.h等&#xff09; 新建的工程先搭建框…

推荐一款Linux、数据库、Redis、MongoDB统一管理平台!

官方演示 状态查看 ssh 终端 文件操作 数据库操作 sql 编辑器 在线增删改查数据 Redis 操作 Mongo 操作 系统管理 账号管理 角色管理 资源管理 一.安装 1.下载安装包 cd /opt wget https://gitee.com/dromara/mayfly-go/releases/download/v1.7.1/mayfly-go-linux-amd64.zi…

CES 2024:AI赋能机器人,国产机器人更亮眼

原创 | 文 BFT机器人 一年一度的国际消费电子展(CES)又与我们见面了。作为全球消费电子和科技创新的盛会&#xff0c;CES每年都吸引着无数目光。今年&#xff0c;AI赋能机器人成为展会的一大亮点&#xff0c;而国产机器人更是凭借其创新技术和实用功能&#xff0c;成为全场焦点…

使用QT实现播放gstreamer的命令(二)

一、前言 上一篇文章写到了&#xff0c;如何快速使用C来执行gstreamer的命令&#xff0c;如何在QT中显示gstreamer的画面&#xff0c;原文如下&#xff1a; https://blog.csdn.net/Alon1787/article/details/135107958 二、近期的其他发现&#xff1a; 1.gstreamer的画面显示在…

蓝桥杯AT24C02问题记录

问题1&#xff1a;从这个图片上可以看出这两个在IIC的.c文件里延时时间不一样&#xff0c;第一张图使用了15个_nop_(); 12M晶振机器周期是 1/12M*121uS&#xff1b;nop()要延时1个指令周期。延时时间不对会对时序产生影响&#xff0c;时序不对&#xff0c;则AT24C02有没被使用…

DAY34:贪心算法part、1005\134\135

Leetcode: 1005 K次取反后最大化的数组和 基本思路 这道题的思路比较简单&#xff0c;如果有负数&#xff0c;就先把最大的负数转化成正数&#xff0c;如果全部转换完之后还有k剩余&#xff0c;就将最小的正数反复正负变化。但是需要注意一点代码的写法。 代码注意点 定义绝…

关于Spring Boot和MyBatis常见的十道面试题

拦截器和过滤器有什么区别&#xff1f; 拦截器&#xff08;Interceptor&#xff09;和过滤器&#xff08;Filter&#xff09;都是用于在请求道道目标资源的之前或之后进行处理的组件。主要区别有以下几点&#xff1a; 依赖对象不同&#xff1a;过滤器是来时Servlet&#xff0…

input、textarea禁止输入空格,并绑定回车事件

一、原生环境 1. 禁止输入空格 <input type"text" v-model"value" οnkeyup"this.valuethis.value.replace(/\s/g,)" /><textarea type"text" v-model"value" οnkeyup"this.valuethis.value.replace(/\s/g…

IDEA安装MyBatisX插件

IDEA工具在开发人员中经常使用&#xff0c;从dao层到xml文件对应的查看很费劲&#xff0c;这时候就有相应的插件工具出现了MyBatisX。他的好处如下&#xff1a; mapper and xml can jump back and forth mybatis.xml,mapper.xml prompt mapper and xml support auto prompt lik…

将多个excel文件中的特定数据汇总到一个excel中

比如5000个excel文件中都有1月2日的交易数据。现在需要将每个文件中1月2日的数据提出来&#xff0c;组成一个新的excel文件&#xff0c;即1月2日的交易数据文件&#xff0c;以1月2日命名。下面的程序是将5000只股票1月2日的交易数据提出来&#xff0c;形成一个1月2日所有股票的…

Netty核心——Reactor下篇(十)

任务队列中的Task有3种典型使用场景 用户程序自定义的普通任务 比如有一个非常耗时长的业务 异步执行提交该Channel对应的NioEventLoop的TaskQueue中 用户自定义定时任务 该任务提交到scheduleTaskQueue中 非当前Reactor线程调用Channel的各种方法 例如在推送系统的业务线程…

大数据StarRocks(八):资源隔离实战

前言 自 2.2 版本起&#xff0c;StarRocks 支持资源组管理&#xff0c;集群可以通过设置资源组&#xff08;Resource Group&#xff09;的方式限制查询对资源的消耗&#xff0c;实现多租户之间的资源隔离与合理利用。在 2.3 版本中&#xff0c;StarRocks 支持限制大查询&#…

Apache Paimon基础记录

基本都是在官网的学习&#xff0c;简单记录一下其中的核心特点 Apache Paimon 官网 Apache Paimon | Apache Paimon 根据官网介绍去快速了解 paimon 是用来设计做什么&#xff0c;可以做什么&#xff0c;对比与其他数据湖有什么特点&#xff0c;如何使用 Paimon 特点 前身…

酒鬼酒2024年展望:稳发展动能,迈入恢复性增长轨道

文 | 琥珀酒研社 作者 | 渡过 最近几个月来&#xff0c;白酒估值回落到近十年来低位&#xff0c;反映出了整个白酒行业的市场低迷和虚弱现状。不管是头部企业五粮液、泸州老窖&#xff0c;还是区域酒企口子窖、金种子酒等&#xff0c;最近都通过“回购”或“增持”&#xff0…

【C语言】【力扣】刷题小白的疑问

一、力扣做题时的答案&#xff0c;没有完整的框架 疑问&#xff1a; 在学习C语言的初始&#xff0c;就知道C语言程序离不开下面这个框架&#xff0c;为什么力扣题的解答往往没有这个框架&#xff1f; #include <stdio.h>int main() {return 0; } 解答&#xff1a; 力扣平…