Mybatis-Pagehelper参数supportMethodsArguments引起的血案

news2024/11/25 18:41:47

0x00 背景

一个历史悠久的项目,使用的技术栈主要是 spring cloud 体系,属于 service 范畴,不给外部提供接口,但是集成了 myabtis-pagehelper,具体的版本如下:

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.6</version>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.1</version>
</dependency>

相关的配置:

pagehelper:
  helperDialect: mysql
  reasonable: true
  supportMethodsArguments: true
  params: count=countSql

0x01 现象描述

同事在这个项目中新增加了一个总能,属于定时执行的,循环取数据,每次取 1000 条,但是上线后发现第一次能正常查询出数据,但是第二次往后就查询不出数据了,但是数据库中是有数据的。SQL 如下:

-- sql 已经做简化处理
select
    *
from ${tableName}
where type = #{type,jdbcType=VARCHAR}
    and time >= #{time,jdbcType=TIMESTAMP}
    <if test="pageSize != null and pageSize != '' and pageNum!=null and pageNum!=''">
        limit #{pageNum}, #{pageSize}
    </if>

0x02 问题分析

刚刚开始以为是 sql 和数据的问题,一顿分析,将 sql 的参数参数打印出来后,用工具查询发现是能查询出数据的。由此判断不是参数以及sql 的问题,于是添加 mybatis 的参数将 sql 打印出来。

mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

查看查询的过程, 发现每一次查询会先执行一个 count 操作,查询总数,总数查询完成后,再去执行查询操作。第一次 count 是有数据,但是第二次查询 count 查询的总数为 0,导致也就不执行查询操作了。看完查询过程后,同事说他这个不是分页,我有个疑问为啥会执行分页操作呢,但是也没多想。继续排查对比。

经过对比前后两次的 count 的 sql 发现,第二次的 count 的 sql 多了一个 limit,而此时的 pageNum 和 pageSize 变成了 1,1。 count 的结果总列数就是 1,limit 1, 1 后肯定是没有结果的。

在这里插入图片描述

0x03 问题解决

发现这个情况后,前面说过他应该不走分页逻辑,应该是正常自定义 limit,也就是说不应该会前置执行 count 计数查询,而应该直接去查询数据。猜想是 pageNum 和 pageSize 两个参数导致的,将参数改名后发现正常执行查询而不执行 count 操作了。

那么究竟是为啥会这样呢,经过查看源码,发现在 PageParams 中有如下的逻辑:

} else if (parameterObject instanceof IPage || supportMethodsArguments) {
                try {
                    page = PageObjectUtil.getPageFromObject(parameterObject, false);
                } catch (Exception e) {
                    return null;
                }
            }

如果参数实现了 IPage 接口或者 supportMethodsArguments 为 true 就会从参数中获取 pageNum 和 pageSize 参数,也就是当 supportMethodsArguments 为 true 时并且参数中有 pageNum 和 pageSize 参数时,会执行分页的相关逻辑。

0x04 总结

总的来说,supportMethodsArguments 为 true 时需要特别注意,传递的参数中不能有 pageNum 和 pageSize 参数,否则会执行分页逻辑。

带着好奇心去看了一下 pagehepler 的源码,发现某些特殊的 sql 走分页逻辑时,会重写成子查询,比如:

select so.id,so.address,so.area_code,so.area_id,so.del_flag,so.email,so.fax,so.grade,so.icon,so.master, so.name,so.parent_id,so.parent_ids,so.phone,so.remarks,so.type,so.zip_code from sys_organization so LEFT JOIN sys_user_organization suo ON (suo.org_id = so.id or FIND_IN_SET(suo.org_id,so.parent_ids)) where suo.user_id = ? group by so.id LIMIT ? "

生成的 count 语句是:

SELECT count(0) FROM (SELECT so.id, so.address, so.area_code, so.area_id, so.del_flag, so.email, so.fax, so.grade, so.icon, so.master, so.name, so.parent_id, so.parent_ids, so.phone, so.remarks, so.type, so.zip_code FROM sys_organization so LEFT JOIN sys_user_organization suo ON (suo.org_id = so.id OR FIND_IN_SET(suo.org_id, so.parent_ids)) WHERE suo.user_id = ? GROUP BY so.id LIMIT ?) table_count

查看了一下源码是有特殊的判断,我们遇到的那个 sql 不满条件,所以只是简单的重写了 sql,没有重写成子查询。

因为是 count 语句的话其实不应该有 limit,有 limit 的话多多少少有点问题。也尝试修复了一下,虽然能重写成子查询,虽然查询 count 正常了,后续正常的查询就不正常(需要处理 sql 的参数,看逻辑后续会还拼接 limit 导致语法错误,想想也没有啥意义(虽然带了 limit但是可能也不是分页),所以还是放弃了。后续关注下,看看作者大大有没有更好的解决办法。

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

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

相关文章

【100天精通Python】Day55:Python 数据分析_Pandas数据选取和常用操作

目录 Pandas数据选择和操作 1 选择列和行 2 过滤数据 3 添加、删除和修改数据 4 数据排序 Pandas数据选择和操作 Pandas是一个Python库&#xff0c;用于数据分析和操作&#xff0c;提供了丰富的功能来选择、过滤、添加、删除和修改数据。 1 选择列和行 Pandas 提供了多种…

VS2022+CMAKE+OPENCV+QT+PCL安装及环境搭建

VS2022安装&#xff1a; Visual Studio 2022安装教程&#xff08;千字图文详解&#xff09;&#xff0c;手把手带你安装运行VS2022以及背景图设置_vs安装教程_我不是大叔丶的博客-CSDN博客 CMAKE配置&#xff1a; win11下配置vscodecmake_心儿痒痒的博客-CSDN博客 OPENCV配…

网络安全行业岗位缺口有多大?看看美国有多少岗位空缺

网络安全行业岗位缺口一直很大&#xff0c;在各类统计中其实并不能完全客观的反应这个缺口&#xff0c;不过都可以作为一个参考。同时&#xff0c;网络安全行业岗位的人员能力参差不齐&#xff0c;不仅仅在数量上有所欠缺&#xff0c;同时从质量上更加加剧了对人才的需求。我们…

高效开发工具:提升 REST API 开发效率

本文将介绍如何使用 Apifox 开发 REST API&#xff0c;并展示 Apifox 的一些关键功能。 我们可以先了解下&#xff1a;REST API 简介 - RESTful Web 服务 步骤 1&#xff1a;创建一个 Apifox 账户 首先&#xff0c;你需要在 Apifox 上创建一个账户。 步骤 2&#xff1a;创建…

React 18 使用 Context 深层传递参数

参考文章 使用 Context 深层传递参数 通常来说&#xff0c;会通过 props 将信息从父组件传递到子组件。但是&#xff0c;如果必须通过许多中间组件向下传递 props&#xff0c;或是在应用中的许多组件需要相同的信息&#xff0c;传递 props 会变的十分冗长和不便。Context 允许…

智能合约安全分析,Vyper 重入锁漏洞全路径分析

智能合约安全分析&#xff0c;Vyper 重入锁漏洞全路径分析 事件背景 7 月 30 日 21:10 至 7 月 31 日 06:00 链上发生大规模攻击事件&#xff0c;导致多个 Curve 池的资金损失。漏洞的根源都是由于特定版本的 Vyper 中出现的重入锁故障。 攻击分析 通过对链上交易数据初步分…

高速人工智能无人机首次击败世界冠军赛车手

大学创造了第一个能够在无人机比赛中击败人类的自主系统。 周三&#xff0c;苏黎世大学和英特尔公司的一组研究人员宣布的他们开发了一个名为Swift的自主无人机系统&#xff0c;可以在第一人称视角下击败人类冠军(FPV)无人驾驶赛车。虽然人工智能以前在像国际象棋这样的游戏中击…

软件测试/测试开发丨建立质量保障体系,软件质量提升90%!原来是这个秘诀...

在现代软件开发领域&#xff0c;质量保障一直是备受争议的话题。关于测试角色在软件全流程中的价值、是否存在一套软件测试方法论以及如何衡量质量和效率的问题一直困扰着业界。为了能让大家更深入的学习质量保障体系&#xff0c;霍格沃兹测试开发学社邀请了大厂的资深测试经理…

modprobe命令及其与insmod depmod的区别

1. modprobe命令详解 modprobe工具可以智能的添加和删除一个模块&#xff0c;之所以说它智能&#xff0c;是因为它能够通过配置的一些预定义的规则解析出模块之间的依赖关系&#xff0c;并且自动加载依赖的模块。 modprobe会从 /lib/modules/uname -r目录中查找要加载的模块以…

Nginx从安装到使用,反向代理,负载均衡

什么是Nginx&#xff1f; 文章目录 什么是Nginx&#xff1f;1、Nginx概述1.1、Nginx介绍1.2、Nginx下载和安装1.3、Nginx目录结构 2、Nginx命令2.1、查看版本2.2、检查配置文件正确性2.3、启动和停止2.4、重新加载配置文件2.5、环境变量的配置 3、Nginx配置文件结构4、Nginx具体…

面向更大屏幕的片段

目前为止&#xff0c;只做过小屏幕设备运行应用。 本文中将创建灵活的用户界面&#xff0c;根据运行应用的设备让应用有不同的外观和行为。 之前我们创建了在手机上运行的Workout应用版本。但是在一个平板上运行这个应用时&#xff0c;应用的表现几乎是一样的。不过由于屏幕更大…

2023年数维杯数学建模A题河流-地下水系统水体污染研求解全过程文档及程序

2023年数维杯数学建模 A题 河流-地下水系统水体污染研 原题再现&#xff1a; 河流对地下水有着直接地影响&#xff0c;当河流补给地下水时&#xff0c;河流一旦被污染&#xff0c;容易导致地下水以及紧依河流分布的傍河水源地将受到不同程度的污染&#xff0c;这将严重影响工…

STM32 CAN快速配置(HAL库版本)

STM32 CAN快速配置&#xff08;HAL库版本&#xff09; 目录 STM32 CAN快速配置&#xff08;HAL库版本&#xff09;前言1 软件编程1.1 初始化1.1.1 引脚设置1.1.2 CAN参数设置1.1.3 CAN滤波器设置 1.2 CAN发送1.3 CAN接收 2 运行测试结束语 前言 控制器局域网总线&#xff08;CA…

vscode debug python launch.json添加args不起作用

问题 为了带入参数调试python 程序&#xff0c;按照网上搜到的教程配置了lauch.json文件&#xff0c;文件中添加了"args": [“model” “0” “path”] {// 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。// 欲了解更多信息&#xff0c;请访问: h…

恢复iTunes备份看这里,2招教你搞定!

iTunes除了是一款免费的数字媒体播放程序以外&#xff0c;苹果用户还可以借助iTunes对自己的iPhone进行全面的备份和恢复&#xff0c;并且在设备损坏或者数据&#xff0c;也能够帮助用户快速恢复数据。当您的数据意外丢失后&#xff0c;该如何从itunes备份中恢复数据呢&#xf…

Shell 运算符及语法结构

目录 一、Shell运算符 1.1 表达式expr 1.2 运算操作 1.3 操作实例 二、Shell条件判断 2.1 基本语法 2.2 值、权限、类型、多条件判断 三、Shell流程控制 3.1 if 流程语法 3.2 case 流程语法 3.3 for 流程语法 3.4 内部运算符 3.5 while循环流程语法 四、Shell读…

香港物流公司新世纪储运申请1125万美元美元纳斯达克IPO上市

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;香港物流公司新世纪储运New Century Logistics (BVI) Limited&#xff0c;近期已向美国证券交易委员会&#xff08;SEC&#xff09;提交招股书&#xff0c;申请在纳斯达克IPO上市&#xff0c;股票…

865. 具有所有最深节点的最小子树(javascript)865. Smallest Subtree with all the Deepest Nodes

给定一个根为 root 的二叉树&#xff0c;每个节点的深度是 该节点到根的最短距离 。 返回包含原始树中所有 最深节点 的 最小子树 。 如果一个节点在 整个树 的任意节点之间具有最大的深度&#xff0c;则该节点是 最深的 。 一个节点的 子树 是该节点加上它的所有后代的集合…

【C++学习笔记】4、变量

文章目录 【 1、变量的定义 】【 2、变量的声明 】示例 【 3、左值和右值 】 变量&#xff1a;相当于是程序可操作的数据存储区的名称。在 C 中&#xff0c;有多种变量类型可用于存储不同种类的数据。C 中每个变量都有指定的类型&#xff0c;类型决定了变量存储的大小和布局&am…

动态规划之简单多状态

简单多状态 1. 按摩师&#xff08;easy&#xff09;2. 打家劫舍II &#xff08;medium&#xff09;3. 删除并获得点数&#xff08;medium&#xff09;4. 买卖股票的最佳时机含冷冻期&#xff08;medium&#xff09;5. 买卖股票的最佳时机III&#xff08;hard&#xff09; 1. 按…