当前位置: 首页 > news >正文

PageHelper自定义Count查询及其优化

PageHelper自定义Count查询及其优化

文章目录

  • PageHelper自定义Count查询及其优化
    • 一:背景
      • 1.1、解决方法
    • 二:利用反射判断请求参数是否有模糊查询
      • 2.1、分页不执行count
      • 2.2、思路
      • 2.3、代码示例
    • 三:自定义COUNT查询SQL(只适用于单表)
      • 3.1、局限性
      • 3.2、使用方式
    • 四:各种模糊查询XML中示例

一:背景

PageHelper默认情况下会帮我们根据查询语句自动生成COUNT查询SQL,但是有些情况下,PageHelper自动生成COUNT查询SQL存在效率问题。比如,其中使用了GROUP BY语句,多表关联,生成的COUNT查询SQL查询效率很慢

1.1、解决方法

1.count()有优化空间的直接优化,Count执行条件慢无外乎索引是否命中,执行SQL是否多表关联

2.count()没办法优化的,只能从业务入手,取消关联的一些条件查询

3.不返回count总条数,只能一页一页往下翻

4.缓存总条数,实时性保证不保证

5.异步查询加载,前端后端一起优化

也就是点击一次请求查询两个接口,list接口肯定很快返回,可以直接进行列展示,供用户操作查看等;
count接口返回较慢,分页插件下面展示loading(提示正在加载),异步执行完成后告诉前端

6.彻底解决:引入ES或其他数据库

7.代码层面:投机取巧(二:利用反射判断请求参数是否有模糊查询)

每次请求分页接口,没有任何条件查询的时候,count会计算总条数,数据量大时非常耗时;但是模糊查询的话,速度还可以接受;是否有一种方法可以:如果只是有pageIndex和pageSize参数的时候,我用自定义的count;如果有其他模糊条件查询的时候,我选择pageHelper自带的count,执行原有复杂SQL语句,维持count准确性

二:利用反射判断请求参数是否有模糊查询

2.1、分页不执行count

PageHelper.startPage(req.getCurPage(), req.getPageSize(),false);
如果将此参数设置为false,pageHlper不执行count方法;

2.2、思路

1.只有分页参数--》不执行默认count方法,设置为false--》自定义count--》返回自定义count总条数2.有模糊查询分页参数--》执行默认count方法,设置为true--》pageHelper自带count--》count参数pageHelper会返回

2.3、代码示例

 // 定义一个私有静态列表来存储需要忽略的字段名称,填写当前类的字段private static final List<String> IGNORED_FIELDS = Arrays.asList("curPage", "pageSize");//用作分页count选择,如果原始分页,选择全表差,反之用条件查public boolean areAllFieldsEmptyExceptIgnored() {//获取父类的字段//Field[] declaredFields = this.getClass().getSuperclass().getDeclaredFields();//只获取了当前类的字段for (Field field : this.getClass().getDeclaredFields()) {// 忽略静态字段和transient字段if (java.lang.reflect.Modifier.isStatic(field.getModifiers()) ||java.lang.reflect.Modifier.isTransient(field.getModifiers())) {continue;}// 忽略配置列表中的字段if (IGNORED_FIELDS.contains(field.getName())) {continue;}// 确保私有字段也可以访问field.setAccessible(true);try {// 获取字段值Object value = field.get(this);//检查字段值是否为空// 检查字段值是否为空if (value instanceof String && ((String) value).isEmpty()) {//字段为空字符串,这是允许的,继续检查下一个字段continue;} else if (value instanceof String) {// 字段为非空字符串return false;} else if (value instanceof List && ((List<?>) value).isEmpty()) {// 字段为非空列表,这是允许的,继续检查下一个字段continue;}else if (value instanceof List) {//字段为非空集合return false;}  else if (value != null) {//字段为非空对象return false;}} catch (IllegalAccessException e) {// 处理可能的非法访问异常throw new RuntimeException("Error accessing field: " + field.getName(), e);}}//所有字段都是空的return true;}

这段反射说明:如果只有分页参数,会返回true;如果有模糊查询参数,会返回false;需要忽略的字段,支持自己设置

        boolean status = req.areAllFieldsEmptyExceptIgnored();PageHelper.startPage(req.getCurPage(), req.getPageSize(),!status);List<GoodsSpu> resultList =goodsSpuMapper.goodsSpuList(daoReq);PageInfo<GoodsSpu> pageInfo = new PageInfo<>(resultList);if (status) {//count全查pageInfo.setTotal(goodsSpuMapper.goodsSpuListCount(daoReq));}else{//count条件查,走默认分页的count}
<select id="goodsSpuList" parameterType="com.kkd.goods.model.in.GoodsSpuListDaoReq" resultType="com.kkd.goods.entity.GoodsSpu">select DISTINCT r.id dis_id,r.* from(select gsp.* from gd_goods_spu gspLEFT JOIN gd_goods_sku gsk on gsp.spu=gsk.spuLEFT JOIN gd_goods_sku_upc gsu on gsp.spu=gsu.spuLEFT JOIN gd_goods_shop_category_relation gscr on gsp.spu=gscr.spuwheregsp.is_delete=0and gsp.org_id=#{orgId}<if test="name != null and name != '' ">and gsp.`name`like concat('%',#{name},'%')</if><if test="spuList != null and spuList.size > 0">AND  gsp.spu IN<foreach item="id" index="index" collection="spuList" open="(" separator="," close=")">#{id}</foreach></if><if test="skuList != null and skuList.size > 0">AND  gsk.sku IN<foreach item="id" index="index" collection="skuList" open="(" separator="," close=")">#{id}</foreach></if><if test="upcList != null and upcList.size > 0">AND  gsu.upc IN<foreach item="id" index="index" collection="upcList" open="(" separator="," close=")">#{id}</foreach></if><if test="categoryCodes != null and categoryCodes.size > 0">AND  gsp.category_code IN<foreach item="id" index="index" collection="categoryCodes" open="(" separator="," close=")">#{id}</foreach></if><if test="shopCategoryIds != null and shopCategoryIds.size > 0">AND  gscr.shop_category_id IN<foreach item="id" index="index" collection="shopCategoryIds" open="(" separator="," close=")">#{id}</foreach></if><if test="ePlatformCategoryId != null">and gsp.e_platform_category_id=#{ePlatformCategoryId}</if><if test="isNormal != null">and gsp.normal=#{isNormal}</if><if test="imageEmpty != null  and imageEmpty == 1 ">and gsp.images is null</if><if test="isMaster != null ">and gsp.`master` = #{isMaster}</if><if test="masterSpu != null and masterSpu !='' ">and gsp.`master_spu` = #{masterSpu}</if>ORDER BY gsp.update_time desc) r
</select>
<select id="goodsSpuListCount" resultType="java.lang.Long" parameterType="com.kkd.goods.model.in.GoodsSpuListDaoReq">select count(*) from gd_goods_spu gspwheregsp.is_delete=0and gsp.org_id=#{orgId}
</select>

三:自定义COUNT查询SQL(只适用于单表)

3.1、局限性

1.对于单表查询:分页执行的sql执行效率都慢,count执行的时候首先考虑命中索引,如果拆分出来效率能得到提升再用
2.对于多表查询:如果查询条件仅仅只是主表中的条件,此方法适用如果查询条件需要从表中的条件,自定义的这个count就不满足
3.缓存count,业务上总数实时性要求不高,或者总数变化不快的情况下可以使用
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.0.4</version>
</dependency>

image-20241209165918906

3.2、使用方式

原有的代码不需要动,只需要在Mybatis的xml文件里添加一个count查询
这里注意以下三点即可:

  1. id和对应的查询语句保持一致,并且以 _COUNT 结尾
  2. 入参和对应的查询语句保持一致
  3. 出参为 resultType=“Long”
<select id="goodsSpuList_COUNT" parameterType="com.kkd.goods.model.in.GoodsSpuListDaoReq" resultType="java.lang.Long">select count(*)from gd_goods_spu gspwhere gsp.is_delete = 0and gsp.org_id = #{orgId}
</select>

四:各种模糊查询XML中示例

    <select id="goodsSpuList" parameterType="com.kkd.goods.model.in.GoodsSpuListDaoReq" resultType="com.kkd.goods.entity.GoodsSpu">select DISTINCT r.id dis_id,r.* from(select gsp.* from gd_goods_spu gspLEFT JOIN gd_goods_sku gsk on gsp.spu=gsk.spuLEFT JOIN gd_goods_sku_upc gsu on gsp.spu=gsu.spuLEFT JOIN gd_goods_shop_category_relation gscr on gsp.spu=gscr.spuwheregsp.is_delete=0and gsp.org_id=#{orgId}<if test="name != null and name != '' ">and gsp.`name`like concat('%',#{name},'%')</if><if test="spuList != null and spuList.size > 0">AND  gsp.spu IN<foreach item="id" index="index" collection="spuList" open="(" separator="," close=")">#{id}</foreach></if><if test="skuList != null and skuList.size > 0">AND  gsk.sku IN<foreach item="id" index="index" collection="skuList" open="(" separator="," close=")">#{id}</foreach></if><if test="upcList != null and upcList.size > 0">AND  gsu.upc IN<foreach item="id" index="index" collection="upcList" open="(" separator="," close=")">#{id}</foreach></if><if test="categoryCodes != null and categoryCodes.size > 0">AND  gsp.category_code IN<foreach item="id" index="index" collection="categoryCodes" open="(" separator="," close=")">#{id}</foreach></if><if test="shopCategoryIds != null and shopCategoryIds.size > 0">AND  gscr.shop_category_id IN<foreach item="id" index="index" collection="shopCategoryIds" open="(" separator="," close=")">#{id}</foreach></if><if test="ePlatformCategoryId != null">and gsp.e_platform_category_id=#{ePlatformCategoryId}</if><if test="isNormal != null">and gsp.normal=#{isNormal}</if><if test="imageEmpty != null  and imageEmpty == 1 ">and gsp.images is null</if><if test="isMaster != null ">and gsp.`master` = #{isMaster}</if><if test="masterSpu != null and masterSpu !='' ">and gsp.`master_spu` = #{masterSpu}</if>ORDER BY gsp.update_time desc) r</select>

参考:Pagehelper自定义count查询

相关文章:

PageHelper自定义Count查询及其优化

PageHelper自定义Count查询及其优化 文章目录 PageHelper自定义Count查询及其优化一&#xff1a;背景1.1、解决方法 二&#xff1a;利用反射判断请求参数是否有模糊查询2.1、分页不执行count2.2、思路2.3、代码示例 三&#xff1a;自定义COUNT查询SQL(只适用于单表)3.1、局限性…...

【数据结构】哈夫曼树

哈夫曼树 路径长度&#xff1a;从树中一个结点到另一个结点之间的分支构成这两个节点之间的路径&#xff0c;路径上的分支数目称为路径长度 树的带权路径长度&#xff1a;树中所有叶子结点的带权路径长度之和&#xff0c;通常记为WPL ∑ k 1 n w k l k \sum^{n}_{k1}w_kl_k …...

springboot422甘肃旅游服务平台代码-(论文+源码)_kaic

摘 要 使用旧方法对甘肃旅游服务平台的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在甘肃旅游服务平台的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。这次开发的…...

docker中安装minio

1.首先需要搜索可用镜像&#xff0c;当然也可以不用 docker search minio/minio 2.拉取镜像 docker pull minio/minio 3.在本地新建两个文件夹路径 mkdir -p /opt/minio/datamkdir -p /opt/minio/config解释一下&#xff0c;data是文件存储的首路径。config是配置路径&…...

golang实现简单的reids服务2

golang实现redis兼容的redis服务实现redis兼容的redis服务思路 golang实现redis兼容的redis服务 之前做的redis服务是通过tcp封装的自定义协议 原版项目地址:https://github.com/dengjiayue/my-redis.git 那么能不能实现一个redis兼容的redis服务,这样一般的redis包也可以调…...

跟李笑来学美式俚语(Most Common American Idioms): Part 67

Most Common American Idioms: Part 67 前言 本文是学习李笑来的Most Common American Idioms这本书的学习笔记&#xff0c;自用。 Github仓库链接&#xff1a;https://github.com/xiaolai/most-common-american-idioms 使用方法: 直接下载下来&#xff08;或者clone到本地…...

QT 中 QDateTime::currentDateTime() 输出格式备查

基础 QDateTime::currentDateTime() //当前的日期和时间。 QDateTime::toString() //以特定的格式输出时间&#xff0c;格式 yyyy: 年份&#xff08;4位数&#xff09; MM: 月份&#xff08;两位数&#xff0c;07表示七月&#xff09; dd: 日期&#xff08;两位数&#xff0c…...

安卓手机怎么轻松转换更新ip网络地址

随着移动互联网的快速发展&#xff0c;IP地址作为网络身份标识的重要性日益凸显。对于安卓手机用户来说&#xff0c;但有时候我们希望能够轻松转更换ip地址&#xff0c;以提高网络安全性或访问特定内容的需要。那么&#xff0c;安卓手机如何更换IP地址呢&#xff1f;本文将为您…...

spring项目添加本地依赖,报java程序包不存在

删除引入程序中的iml文件 重新在当前项目目录下构建项目...

嵌入式硬件-- 元器件焊接

1.锡膏的使用 锡膏要保存在冰箱里。 焊接排线端子&#xff1b;138度的低温锡&#xff08;锡膏&#xff09;&#xff0c; 第一次使用&#xff0c;直接拿东西挑一点涂在引脚上&#xff0c;不知道多少合适&#xff0c;加热台加热到260左右&#xff0c;放在上面观察锡融化&#…...

物联网入门-Arduino的下载与配置教程(以ESP32为例)-2024

教程介绍 本次教程主要讲述如何下载与配置Arduino&#xff0c;以及开发版对应驱动的下载安装 原文链接&#xff1a;物联网入门-Arduino的下载与配置教程(以ESP32为例)-2024 步骤概述 1&#xff1a;下载Arduino 2&#xff1a;安装Arduino 3&#xff1a;下载安装驱动 4&am…...

防火墙旁挂部署+故障切换

一、实验环境 华为ENSP 二、拓扑 三、目的 1、内网PC1访问Server 2、防火墙旁挂部署&#xff0c;对流量进行过滤&#xff0c;防火墙挂掉之后&#xff0c;内网PC1能继续访问到Server 3、防火墙恢复正常后&#xff0c;流量能回切至防火墙转发 四、思路&#xff1a; 1、AR1…...

PyTorch基本使用-张量的基本运算及函数计算

文章目录 1. 张量数值计算1. 1 张量基本运算1.2 点乘运算1.3 矩阵运算 2. 张量运算函数 1. 张量数值计算 1. 1 张量基本运算 加减乘除取负号&#xff1a; add、sub、mul、div、neg add_ 、sub_、 mul_ 、div_、 neg_ (其中带下划线的版本会修改原数据) data torch.randin…...

C#--方法

C#的代码包装 三种实现途径&#xff1a;方法、类和名字空间。 • 方法是包含一系列语句的代码块。 • 类用于组合类&#xff0c;方法&#xff0c;属性。 • 将多个相关类组合成名字空间。 静态方法和静态变量 • 静态成员 在类中&#xff0c;使用static修饰符声明的成员称为静态…...

前端权限控制

前端权限控制 一、路由权限&#xff08;控制页面访问&#xff09; vue // router.js const routes [{path: /dashboard,name: Dashboard,component: () > import(/views/Dashboard.vue),meta: { requiresAuth: true, roles: [admin, manager] }},{path: /user,name: Use…...

mac下载安装jdk

背景 长时间不折腾mac全部忘记 特此记录 安装 1.下载jdk 根据需要下载对应的jdk 我直接 下载到/Applicatiions目录 https://www.oracle.com/java/technologies/downloads/#java8-mac 2.解压 cd /Applicatiions tar -zxvf jdk-8u431-macosx-x64.tar.gz 3.配置环境 …...

在线PS工具:UI设计的创新选择

对于刚踏入UI设计领域的新手来说&#xff0c;选择合适的在线Photoshop替代工具是至关重要的。市场上存在众多的在线设计工具&#xff0c;让人难以抉择。以下是10个值得尝试的在线PS工具&#xff0c;希望能帮助你找到最适合你的那一款。 Adobe Photoshop Photoshop是设计师们长…...

生成式AI概览与详解

1. 生成式AI概览&#xff1a;什么是大模型&#xff0c;大模型应用场景&#xff08;文生文&#xff0c;多模态&#xff09; 生成式AI&#xff08;Generative AI&#xff09;是指通过机器学习模型生成新的数据或内容的人工智能技术。生成式AI可以生成文本、图像、音频、视频等多种…...

数据结构与算法学习笔记----树与图的深度优先遍历

数据结构与算法学习笔记----树与图的深度优先遍历 author: 明月清了个风 first publish time: 2024.12.9 pa⭐️这里只有一道题哈哈。 Acwing 846.树的重心 给定一棵树&#xff0c;树中包含 n n n个节点&#xff08;编号 1 ∼ n 1 \sim n 1∼n&#xff09;和 n − 1 n - 1 n…...

IEEE T-RO 软体机器人手指状态估计实现两栖触觉传感

摘要&#xff1a;南方科技大学戴建生院士、林间院士、万芳老师、宋超阳老师团队近期在IEEE T-RO上发表了关于软体机器人手指在两栖环境中本体感知方法的论文。 近日&#xff0c;南方科技大学戴建生院士、林间院士、万芳老师、宋超阳老师团队在机器人顶刊IEEE T-RO上以《Propri…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…...