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 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查询

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Qt 一个简单的QChart 绘图

Qt 一个简单的QChart 绘图 先上程序运行结果图&#xff1a; “sample9_1QChart.h” 文件代码如下&#xff1a; #pragma once#include <QtWidgets/QMainWindow> #include "ui_sample9_1QChart.h"#include <QtCharts> //必须这么设置 QT_CHARTS_USE_NAME…

Hadoop生态圈框架部署 伪集群版(九)- FineBI个人试用版安装与配置

文章目录 前言一、FineBI安装与配置&#xff08;Linux版本&#xff09;1. 下载并上传FineBI安装包脚本文件1.1 下载1.2 上传1.3 安装要求1.3.1 硬件要求1.3.2 软件要求 2. 安装字体及字体配置工具3. 赋予安装包文件权限4. 安装FineBI5. 设置环境变量6. 启动FineBI6.1 启动FineB…

Spring Boot集成Knife4j文档工具

Knife4j 搭建 Knife4j环境的的搭建和Swagger一样都比较简单&#xff0c;只需要极简的配置即可。 maven依赖 我使用的是较高版本的基于openapi规范的依赖包&#xff0c;OpenAPI2(Swagger)规范是Knife4j之前一直提供支持的版本&#xff0c;底层依赖框架为Springfox。 此次在4…

【GIS教程】使用GDAL-Python将tif转为COG并在ArcGIS Js前端加载-附完整代码

目录 一、数据格式 二、COG特点 三、使用GDAL生成COG格式的数据 四、使用ArcGIS Maps SDK for JavaScript加载COG格式数据 一、数据格式 COG&#xff08;Cloud optimized GeoTIFF&#xff09;是一种GeoTiff格式的数据。托管在 HTTP 文件服务器上&#xff0c;可以代替geose…

Elasticsearch+Kibana分布式存储引擎

1.ElaticSearch介绍 ElaticSearch &#xff0c;简称为 ES &#xff0c; ES 是一个开源的高扩展的分布式全文检索引擎&#xff0c;它可以近乎实时的存储、检 索数据&#xff1b;本身扩展性很好&#xff0c;可以扩展到上百台服务器&#xff0c;处理 PB 级别的数据。 ES 也使用 …

Qt之将源代码封装成库文件使用(五)

Qt开发 系列文章 - Code-To-Library&#xff08;五&#xff09; 目录 前言 一、库文件 二、直接封装方式 1.静态库封装 2.动态库封装 3.其它库类型 三、二次重写封装 四、库的使用 1.移植库及头文件 2.添加外部库 总结 前言 库文件是计算机上的一类文件&#xff0c…

Qt 联合Halcon视觉框架(1)

文章目录 效果QHalconWind 类回调函数刷新窗口构造函数保证窗口大小和Halcon 窗口大小一致绘制图片获取坐标点设置坐标点鼠标拖动图片鼠标按下鼠标抬起鼠标双击滚轮放大缩小图片 效果 QHalconWind 类 // HALCON/Qt pattern matching and measure example // // (c) 2004-2017 …

AI大模型学习笔记|人工智能的发展历程、智能体的发展、机器学习与深度学习的基本理论

学习链接&#xff1a;冒死上传&#xff01;价值2W的大模型入门到就业教程分享给大家&#xff01;轻松打造专属大模型助手&#xff0c;—多模态、Agent、LangChain、ViT、NLP_哔哩哔哩_bilibili 百度网盘自己整理的笔记&#xff1a; 通过网盘分享的文件&#xff1a;1-人工智能的…

Vue项目打包部署到服务器

1. Vue项目打包部署到服务器 1.1. 配置 &#xff08;1&#xff09;修改package.json文件同级目录下的vue.config.js文件。 // vue.config.js module.exports {publicPath: ./, }&#xff08;2&#xff09;检查router下的index.js文件下配置的mode模式。   检查如果模式改…

docker的网络类型和使用方式

docker的网络类型 5种网络类型 bridge 默认类型&#xff0c;桥接到宿主机docker0的网络&#xff0c;有点类似于VM虚拟机的NAT网络模型。 案例: docker run --rm -itd --network bridge --name wzy666wzy-bridge alpine host host类型&#xff0c;共享宿主机的网络空间&#…

数字IC后端实现常见的physical only cell都有哪些?如何添加这些cell?

数字IC后端实现阶段常见功能cell有哪些&#xff1f;比如AND&#xff0c;AOI&#xff0c;NAND等。 physical cell有哪些&#xff1f;都是干什么用的&#xff1f; 数字后端零基础入门系列 | Innovus零基础LAB学习Day9 &#xff08;1&#xff09; well tap cells&#xff1a;防止…

c++中类的应用综合练习

整理思维导图 课上类实现> 、<、!、||、&#xff01;和后自增、前自减、后自减运算符的重载 代码部分&#xff1a; #include <iostream> using namespace std; class complex {int rel;int vir; public:complex(int rel,int vir):rel(rel),vir(vir){}complex(){}…

ElasticSearch 搜索、排序、分页功能

一、DSL 查询文档 ElasticSearch 的查询依然是基于 json 风格的 DSL 来实现的。 官方文档&#xff1a;https://www.elastic.co/guide/en/elasticsearch/reference/8.15/query-dsl.html 1.1 DSL 查询分类 常见的查询类型包括&#xff1a; 查询所有&#xff1a;查询出所有数…

mybatis常见错误

1.没有在mybatis.xml里面引入映射文件 2. 连接数据库部分有误 3.控制台输出无误&#xff0c;数据库里只插入了id sql语句有误 正确 <insert id"add" useGeneratedKeys"true" keyProperty"id">insert into t_teacher values (null,#{nam…

GLM-4-Plus初体验

引言&#xff1a;为什么高效的内容创作如此重要&#xff1f; 在当前竞争激烈的市场环境中&#xff0c;内容创作已成为品牌成功的重要支柱。无论是撰写营销文案、博客文章、社交媒体帖子&#xff0c;还是制作广告&#xff0c;优质的内容不仅能够帮助品牌吸引目标受众的注意力&a…

Mac/Windows端长期破解myBase8方法(无需安装火绒)

提醒 不管哪个端&#xff0c;都需要先退出myBase。 Mac 进入用户根目录/Users/c0ny100&#xff0c;即下边是Macintosh HD > 用户 > [你的用户名]这个界面然后按ShiftCommond.&#xff0c;显示隐藏文件。找到.Mybase8.ini文件 打开.Mybase8.ini文件&#xff0c;删除Fir…

Capture绘制元器件(Candance 17.4)

step1&#xff1a;新建元器件库 step2&#xff1a;新建元器件 step3&#xff1a;新建元器件,填写元器件名称以及类型 step4&#xff1a;绘制元器件形状 step5&#xff1a;添加引脚 添加引脚名称以及序号 将GND、VIN等电源属性引脚从Passive改为Power&#xff0c;其余为Passive …

支持自定义离线地图地理区域,查询组件及数据源功能增强,DataEase开源BI工具v2.10.3 LTS发布

2024年12月9日&#xff0c;人人可用的开源BI工具DataEase正式发布v2.10.3 LTS版本。 这一版本的功能变动包括&#xff1a;数据源方面&#xff0c;API数据源和Excel数据源支持对字段类型和长度进行设置&#xff1b;图表方面&#xff0c;离线类地图支持自定义地理区域设置&#…

【Unity学习笔记·第十二】Unity New Input System 及其系统结构和源码浅析

转载请注明出处&#xff1a;&#x1f517;https://blog.csdn.net/weixin_44013533/article/details/132534422 作者&#xff1a;CSDN|Ringleader| 主要参考&#xff1a; 官方文档&#xff1a;Unity官方Input System手册与API官方测试用例&#xff1a;Unity-Technologies/InputS…

STM32F103单片机HAL库串口通信卡死问题解决方法

在上篇文章 STM32F103单片机使用STM32CubeMX创建IAR串口工程 中分享了使用cubeMX直接生成串口代码的方法&#xff0c;在测试的过程中无意间发现&#xff0c;串口会出现卡死的问题。 当串口一次性发送十几个数据的时候&#xff0c;串口感觉像卡死了一样&#xff0c;不再接收数据…