PageHelper自定义Count查询及其优化

news2025/4/6 16:45:30

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 gsp
                                  LEFT JOIN gd_goods_sku gsk on gsp.spu=gsk.spu
                                  LEFT JOIN gd_goods_sku_upc gsu on gsp.spu=gsu.spu
                                  LEFT JOIN gd_goods_shop_category_relation gscr on gsp.spu=gscr.spu
            where
             gsp.is_delete=0
            and 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 gsp
    where
        gsp.is_delete=0
      and 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 gsp
    where gsp.is_delete = 0
    and 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 gsp
                                      LEFT JOIN gd_goods_sku gsk on gsp.spu=gsk.spu
                                      LEFT JOIN gd_goods_sku_upc gsu on gsp.spu=gsu.spu
                                      LEFT JOIN gd_goods_shop_category_relation gscr on gsp.spu=gscr.spu
                where
                 gsp.is_delete=0
                and 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查询

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

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

相关文章

【洛谷】P1223 排队接水(思路详解)

#include <iostream> #include <algorithm> #include <iomanip> using namespace std;int main() {//1. 从标准输入读取人数n&#xff0c;对应题目中在水龙头前排队接水的人数int n; cin >> n;//2. 定义数组N&#xff0c;用于存储每个人接水的时间&am…

WebDAV服务不能上传大文件,文件超过50M报错[0x800700DF]怎么办?

这个问题需要分别从服务端和客户端解决。 1.Windows客户端 解除50M文件限制&#xff0c;Windows访问Webdav服务时&#xff0c;大于50M文件提示错误[错误:0x800700DF] 部署了webdav&#xff0c;Windows10映射网络磁盘&#xff0c;传输文件超过大约50MB的文件会弹出“0x800700…

计算机视觉:学习指南

一、引言 计算机视觉作为人工智能领域的一个重要分支&#xff0c;致力于让计算机理解和解释视觉信息&#xff0c;近年来取得了令人瞩目的进展&#xff0c;广泛应用于安防监控、自动驾驶、图像编辑、医学影像分析等众多领域。从入门到精通计算机视觉需要系统地学习一系列知识和…

vue3-canvas实现在图片上框选标记(放大,缩小,移动,删除)

双图版本&#xff08;模板对比&#xff09; 业务描述&#xff1a;模板与图片对比&#xff0c;只操作模板框选的位置进行色差对比&#xff0c;传框选坐标位置给后端&#xff0c;返回对比结果显示 draw.js文件&#xff1a; 新增了 createUuid&#xff0c;和求取两个数组差集的方…

StarRocks-hive数据类型导致的分区问题

背景&#xff1a; 有个hive的表&#xff0c;是月分区的&#xff08;month_id&#xff09;&#xff0c;分区字段用的是string类型。数据量比较大&#xff0c;为了保证计算性能&#xff0c;所以把数据导入到SR里&#xff0c;构建一个内部表。但是在建表的时候想使用月分区使用pa…

Flume——进阶(agent特性+三种结构:串联,多路复用,聚合)

目录 agent特性ChannelSelector描述&#xff1a; SinkProcessor描述&#xff1a; 串联架构结构图解定义与描述配置示例Flume1&#xff08;监测端node1&#xff09;Flume3&#xff08;接收端node3&#xff09;启动方式 复制和多路复用结构图解定义描述配置示例node1node2node3启…

嵌入式学习(15)-stm32通用GPIO模拟串口发送数据

一、概述 在项目开发中可能会遇到串口不够用的情况这时候可以用通过GPIO来模拟串口的通信方式。 二、协议格式 按照1位起始位8位数据位1位停止位的方式去编写发送端的程序。起始位拉低一个波特率的时间&#xff1b;发送8位数据&#xff1b;拉高一个波特率的时间。 三、代码 …

【Go系列】:全面掌握 Sentinel Go —— 构建高可用微服务的流量控制、熔断、降级与系统防护体系

前言 在现代分布式系统架构中&#xff0c;服务的稳定性和可用性是至关重要的。随着微服务和云原生技术的发展&#xff0c;如何有效地进行流量控制、熔断降级以及系统保护成为了一个关键课题。Sentinel 是阿里巴巴开源的一款面向分布式服务架构的流量控制组件&#xff0c;它不仅…

多模态RAG:通用框架方案调研汇总

阅读原文 多模态检索增强生成是一种新兴的设计范式&#xff0c;允许AI模型与文本、图像、视频等存储进行交互。在介绍多模态 RAG 之前&#xff0c;我们先简单了解一下传统的检索增强生成 (RAG)。 标准 RAG RAG 的理念是找到与用户查询相关的核心信息&#xff0c;然后将该信息…

《HTML 的变革之路:从过去到未来》

一、HTML 的发展历程 图片: HTML 从诞生至今&#xff0c;经历了多个版本的迭代。 &#xff08;一&#xff09;早期版本 HTML 3.2 在 1997 年 1 月 14 日成为 W3C 推荐标准&#xff0c;提供了表格、文字绕排和复杂数学元素显示等新特性&#xff0c;但因实现复杂且缺乏浏览器…

游戏交易系统设计与实现

文末获取源码和万字论文&#xff0c;制作不易&#xff0c;感谢点赞支持。 题目&#xff1a;游戏交易系统设计与实现 摘 要 在如今社会上&#xff0c;关于信息上面的处理&#xff0c;没有任何一个企业或者个人会忽视&#xff0c;如何让信息急速传递&#xff0c;并且归档储存查询…

Mac mini m4本地跑大模型(ollama + llama + ComfyUI + Stable Diffusion | flux)

安装chat大模型&#xff08;不推荐&#xff0c;本地运行的大模型只能聊废话&#xff0c;不如网页版使用openAI等高效&#xff09; 首先下载ollama的安装包 https://ollama.com/ 点击启动访问&#xff1a;http://localhost:11434 Ollama is running 代表已经运行起来了&#x…

精品C++项目推荐:分布式kv存储系统

项目代码直接开源到Github&#xff1a;https://github.com/youngyangyang04/KVstorageBaseRaft-cpp 欢迎去star&#xff0c;fork&#xff01; 项目背景相关 背景 在当今大规模分布式系统的背景下&#xff0c;需要可靠、高可用性的分布式数据存储系统。 传统的集中式数据库在…

Milvus中如何实现全文检索(Full Text Seach)?

在前两篇文章中&#xff08;Milvus python库 pymilvus 常用操作详解之Collection&#xff08;上&#xff09; 和 Milvus python库 pymilvus 常用操作详解之Collection&#xff08;下&#xff09;&#xff09;&#xff0c;我们了解了Milvus基于dense vector和sparse vector实现的…

unity打包web,如何减小文件体积,特别是 Build.wasm.gz

unity打包WebGL&#xff0c;使用的是wasw&#xff0c;最终生成的Build.wasm.gz体积很大&#xff0c;有6.5M&#xff0c;有几个方法可以稍微减小这个文件的大小 1. 裁剪引擎代码&#xff1a; 此步可将大小从6.5减小到 6.2&#xff08;此项默认开启&#xff0c;只是改了裁剪等级…

STM32 CubeMx HAL库 独立看门狗IWDG配置使用

看门狗这里我就不多介绍了&#xff0c;能搜到这篇文章说明你了解 总之就是一个单片机重启程序&#xff0c;设定好超时时间&#xff0c;在超时时间内没有喂狗&#xff0c;单片机就会复位 主要应用在单片机异常重启方面&#xff0c;比如程序跑飞&#xff08;注意程序跑飞时你就…

Selenium:强大的 Web 自动化测试工具

Selenium&#xff1a;强大的 Web 自动化测试工具 在当今的软件开发和测试领域&#xff0c;自动化工具的重要性日益凸显。Selenium 就是一款备受欢迎的 Web 自动化测试工具&#xff0c;它为开发者和测试人员提供了强大的功能和便利。本文将详细介绍 Selenium 是什么&#xff0c…

幼儿园学校养老院供电安全解决方案

一、 电气火灾每年以30%的比例高居各类火灾原因。以50%到80%的比例高居重特大火灾。已成为业界重点关注的对象并为此进行着孜孜不倦的努力。2021年“119”消防日&#xff0c;国家应急管理部消防救援局公布了2021年1至10月份全国火灾形势报告。数据显示&#xff0c;从火灾种类来…

UnityShaderLab-实现沿y轴溶解效果

实现思路&#xff1a; 实现思路同UnityShaderLab-实现溶解效果-CSDN博客 ShaderGraph实现&#xff1a; ShaderLab实现&#xff1a; 效果&#xff1a; 未完待续。。。

5G Multi-TRP R16~R18演进历程

提升小区边缘用户的性能&#xff0c;在覆盖范围内提供更为均衡的服务质量&#xff0c;NR中引入了多TRP协作传输的方案。多TRP协作传输通过多个TRP之间进行非相干联合传输&#xff08;Non Coherent-Joint Transmission&#xff0c;NC-JT&#xff09;、重复传输&#xff0f;接收或…