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>

3.2、使用方式
原有的代码不需要动,只需要在Mybatis的xml文件里添加一个count查询
这里注意以下三点即可:
- id和对应的查询语句保持一致,并且以 _COUNT 结尾
- 入参和对应的查询语句保持一致
- 出参为 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查询及其优化一:背景1.1、解决方法 二:利用反射判断请求参数是否有模糊查询2.1、分页不执行count2.2、思路2.3、代码示例 三:自定义COUNT查询SQL(只适用于单表)3.1、局限性…...
【数据结构】哈夫曼树
哈夫曼树 路径长度:从树中一个结点到另一个结点之间的分支构成这两个节点之间的路径,路径上的分支数目称为路径长度 树的带权路径长度:树中所有叶子结点的带权路径长度之和,通常记为WPL ∑ k 1 n w k l k \sum^{n}_{k1}w_kl_k …...
springboot422甘肃旅游服务平台代码-(论文+源码)_kaic
摘 要 使用旧方法对甘肃旅游服务平台的信息进行系统化管理已经不再让人们信赖了,把现在的网络信息技术运用在甘肃旅游服务平台的管理上面可以解决许多信息管理上面的难题,比如处理数据时间很长,数据存在错误不能及时纠正等问题。这次开发的…...
docker中安装minio
1.首先需要搜索可用镜像,当然也可以不用 docker search minio/minio 2.拉取镜像 docker pull minio/minio 3.在本地新建两个文件夹路径 mkdir -p /opt/minio/datamkdir -p /opt/minio/config解释一下,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这本书的学习笔记,自用。 Github仓库链接:https://github.com/xiaolai/most-common-american-idioms 使用方法: 直接下载下来(或者clone到本地…...
QT 中 QDateTime::currentDateTime() 输出格式备查
基础 QDateTime::currentDateTime() //当前的日期和时间。 QDateTime::toString() //以特定的格式输出时间,格式 yyyy: 年份(4位数) MM: 月份(两位数,07表示七月) dd: 日期(两位数,…...
安卓手机怎么轻松转换更新ip网络地址
随着移动互联网的快速发展,IP地址作为网络身份标识的重要性日益凸显。对于安卓手机用户来说,但有时候我们希望能够轻松转更换ip地址,以提高网络安全性或访问特定内容的需要。那么,安卓手机如何更换IP地址呢?本文将为您…...
spring项目添加本地依赖,报java程序包不存在
删除引入程序中的iml文件 重新在当前项目目录下构建项目...
嵌入式硬件-- 元器件焊接
1.锡膏的使用 锡膏要保存在冰箱里。 焊接排线端子;138度的低温锡(锡膏), 第一次使用,直接拿东西挑一点涂在引脚上,不知道多少合适,加热台加热到260左右,放在上面观察锡融化&#…...
物联网入门-Arduino的下载与配置教程(以ESP32为例)-2024
教程介绍 本次教程主要讲述如何下载与配置Arduino,以及开发版对应驱动的下载安装 原文链接:物联网入门-Arduino的下载与配置教程(以ESP32为例)-2024 步骤概述 1:下载Arduino 2:安装Arduino 3:下载安装驱动 4&am…...
防火墙旁挂部署+故障切换
一、实验环境 华为ENSP 二、拓扑 三、目的 1、内网PC1访问Server 2、防火墙旁挂部署,对流量进行过滤,防火墙挂掉之后,内网PC1能继续访问到Server 3、防火墙恢复正常后,流量能回切至防火墙转发 四、思路: 1、AR1…...
PyTorch基本使用-张量的基本运算及函数计算
文章目录 1. 张量数值计算1. 1 张量基本运算1.2 点乘运算1.3 矩阵运算 2. 张量运算函数 1. 张量数值计算 1. 1 张量基本运算 加减乘除取负号: add、sub、mul、div、neg add_ 、sub_、 mul_ 、div_、 neg_ (其中带下划线的版本会修改原数据) data torch.randin…...
C#--方法
C#的代码包装 三种实现途径:方法、类和名字空间。 • 方法是包含一系列语句的代码块。 • 类用于组合类,方法,属性。 • 将多个相关类组合成名字空间。 静态方法和静态变量 • 静态成员 在类中,使用static修饰符声明的成员称为静态…...
前端权限控制
前端权限控制 一、路由权限(控制页面访问) 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设计领域的新手来说,选择合适的在线Photoshop替代工具是至关重要的。市场上存在众多的在线设计工具,让人难以抉择。以下是10个值得尝试的在线PS工具,希望能帮助你找到最适合你的那一款。 Adobe Photoshop Photoshop是设计师们长…...
生成式AI概览与详解
1. 生成式AI概览:什么是大模型,大模型应用场景(文生文,多模态) 生成式AI(Generative AI)是指通过机器学习模型生成新的数据或内容的人工智能技术。生成式AI可以生成文本、图像、音频、视频等多种…...
数据结构与算法学习笔记----树与图的深度优先遍历
数据结构与算法学习笔记----树与图的深度优先遍历 author: 明月清了个风 first publish time: 2024.12.9 pa⭐️这里只有一道题哈哈。 Acwing 846.树的重心 给定一棵树,树中包含 n n n个节点(编号 1 ∼ n 1 \sim n 1∼n)和 n − 1 n - 1 n…...
IEEE T-RO 软体机器人手指状态估计实现两栖触觉传感
摘要:南方科技大学戴建生院士、林间院士、万芳老师、宋超阳老师团队近期在IEEE T-RO上发表了关于软体机器人手指在两栖环境中本体感知方法的论文。 近日,南方科技大学戴建生院士、林间院士、万芳老师、宋超阳老师团队在机器人顶刊IEEE T-RO上以《Propri…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
