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

接口查询优化:优雅的处理大批量数据及 in 超过 1000 问题

我是 ABin-阿斌:写一生代码,创一世佳话,筑一览芳华。
如果小伙伴觉得不错就一键三连吧~
在这里插入图片描述

文章目录

  • 一、问题点
  • 二、解决方案
    • 1、在业务层面用Java代码进行分页处理
    • 2、使用工具类 List 总数切分
    • 3、自己封装一个分页工具类
        • 工具类代码
      • 案例展示
    • 4、适用于Mybatis SQL写法

一、问题点

  • 有时候在查询数据时可能需要根据【A表】的某个 ID 去获取 【B表】 的具体信息,但是又因为数据量的庞大,我们需要对 【A表】查出来的数据结果进行分页处理之后再循环调用【B表】

二、解决方案

1、在业务层面用Java代码进行分页处理

  • 比如:通过策略ID去获取当前策略下的订单信息,那么为了防止订单信息过多我们可以这么做

在这里插入图片描述

  • 首先将查询获取订单信息在Service层写一个分页接口,然后进行调用
  • 具体的分页参数信息可以根据业务来定,这里进行分批处理,一页:100条
  • 然后进行循环翻页处理

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2、使用工具类 List 总数切分

  • 注意: ListUtil.partition(),这个方法从某种意义上说并没有达到真正分页的效果,因为当我们使用这个方法时,List结果早已执行出来了;我们要做的就是在结果没有出来之前就减少 DB 的压力。

  • 当然,具体业务具体分析,少量的数据可以使用这个方法

  • 直接使用 Hutool 工具类中的 ListUtil.partition(list,100)方法,参数一: 具体 list、参数二: 具体分多少条

3、自己封装一个分页工具类

  • 下面这个工具类适用于 MyBatisPlus

工具类代码

public class MybatisParameterUtils {


    public static <T, F> void cutInParameter(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> column, List<F> coll) throws Exception {
        List<List<F>> newList = splitList(coll, 900);
        if (ObjectUtils.isEmpty(newList)) {
            throw new Exception("参数错误");
        } else if (newList.size() == 1) {
            wrapper.in(column, newList.get(0));
            return;
        }

        wrapper.and(i -> {
            i.in(column, newList.get(0));
            newList.remove(0);
            for (List<F> objects : newList) {
                i.or().in(column, objects);
            }
        });
    }

    public static <T, F> void cutNotInParameter(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> column, List<F> coll) throws Exception {
        List<List<F>> newList = splitList(coll, 900);
        if (ObjectUtils.isEmpty(newList)) {
            throw new Exception("参数错误");
        } else if (newList.size() == 1) {
            wrapper.notIn(column, newList.get(0));
            return;
        }

        wrapper.and(i -> {
            i.in(column, newList.get(0));
            newList.remove(0);
            for (List<F> objects : newList) {
                i.or().notIn(column, objects);
            }
        });
    }


    public static <T, F> void cutInParameter(LambdaQueryChainWrapper<T> wrapper, SFunction<T, ?> column, List<F> coll) throws Exception {
        List<List<F>> newList = splitList(coll, 900);
        if (ObjectUtils.isEmpty(newList)) {
            throw new Exception("参数错误");
        } else if (newList.size() == 1) {
            wrapper.in(column, newList.get(0));
            return;
        }

        wrapper.and(i -> {
            i.in(column, newList.get(0));
            newList.remove(0);
            for (List<F> objects : newList) {
                i.or().in(column, objects);
            }
        });
    }

    public static <T, F> void cutNotInParameter(LambdaQueryChainWrapper<T> wrapper, SFunction<T, ?> column, List<F> coll) throws Exception {
        List<List<F>> newList = splitList(coll, 900);
        if (ObjectUtils.isEmpty(newList)) {
            throw new Exception("参数错误");
        } else if (newList.size() == 1) {
            wrapper.notIn(column, newList.get(0));
            return;
        }

        wrapper.and(i -> {
            i.in(column, newList.get(0));
            newList.remove(0);
            for (List<F> objects : newList) {
                i.or().notIn(column, objects);
            }
        });
    }

    public static <T, F> void cutInParameter(LambdaUpdateWrapper<T> wrapper, SFunction<T, ?> column, List<F> coll) throws Exception {
        List<List<F>> newList = splitList(coll, 900);
        if (ObjectUtils.isEmpty(newList)) {
            throw new Exception("参数错误");
        } else if (newList.size() == 1) {
            wrapper.in(column, newList.get(0));
            return;
        }

        wrapper.and(i -> {
            i.in(column, newList.get(0));
            newList.remove(0);
            for (List<F> objects : newList) {
                i.or().in(column, objects);
            }
        });
    }

    public static <T, F> void cutNotInParameter(LambdaUpdateWrapper<T> wrapper, SFunction<T, ?> column, List<F> coll) throws Exception {
        List<List<F>> newList = splitList(coll, 900);
        if (ObjectUtils.isEmpty(newList)) {
            throw new Exception("参数错误");
        } else if (newList.size() == 1) {
            wrapper.notIn(column, newList.get(0));
            return;
        }

        wrapper.and(i -> {
            i.in(column, newList.get(0));
            newList.remove(0);
            for (List<F> objects : newList) {
                i.or().notIn(column, objects);
            }
        });
    }


    public static <T, F> void cutInParameter(LambdaUpdateChainWrapper<T> wrapper, SFunction<T, ?> column, List<F> coll) throws Exception {
        List<List<F>> newList = splitList(coll, 900);
        if (ObjectUtils.isEmpty(newList)) {
            throw new Exception("参数错误");
        } else if (newList.size() == 1) {
            wrapper.in(column, newList.get(0));
            return;
        }

        wrapper.and(i -> {
            i.in(column, newList.get(0));
            newList.remove(0);
            for (List<F> objects : newList) {
                i.or().in(column, objects);
            }
        });
    }

    public static <T, F> void cutNotInParameter(LambdaUpdateChainWrapper<T> wrapper, SFunction<T, ?> column, List<F> coll) throws Exception {
        List<List<F>> newList = splitList(coll, 900);
        if (ObjectUtils.isEmpty(newList)) {
            throw new Exception("参数错误");
        } else if (newList.size() == 1) {
            wrapper.notIn(column, newList.get(0));
            return;
        }

        wrapper.and(i -> {
            i.in(column, newList.get(0));
            newList.remove(0);
            for (List<F> objects : newList) {
                i.or().notIn(column, objects);
            }
        });
    }


    public static <F> List<List<F>> splitList(List<F> list, int groupSize) {
        int length = list.size();
        // 计算可以分成多少组
        int num = (length + groupSize - 1) / groupSize;
        List<List<F>> newList = new ArrayList<>(num);
        for (int i = 0; i < num; i++) {
            // 开始位置
            int fromIndex = i * groupSize;
            // 结束位置
            int toIndex = Math.min((i + 1) * groupSize, length);
            newList.add(list.subList(fromIndex, toIndex));
        }
        return newList;
    }
}

案例展示

  • 思路就是把条件拆成小于 1000 的组合条件 写 xml 同理
  //                                    这是一个条件wrapper    get方法的方法引用    一个参数list   
    MybatisParameterUtils.cutInParameter(deleteInfoWrapper,   Vo::getId,          list);

4、适用于Mybatis SQL写法

<if test="dto.idList != null and dto.idList.size() > 0">
                and (t.id IN
                <foreach collection="dto.idList" index="index" open="(" close=")" item="item" >
                    <if test="index !=0">
                        <choose>
                            <when test="index % 1000 == 999">) OR t.id IN (</when>
                            <otherwise>,</otherwise>
                        </choose>
                    </if>
                    #{item}
                </foreach>
                )
</if>

相关文章:

  • Linux搭建redis调试环境
  • 精确的数字-C++数据类型
  • C# 中的多线程和异步编程
  • 前端初识算法
  • SQL->基础->进阶
  • keepalived实现nginx负载均衡机高可用
  • 如何通过优化 Python 中的 GPU 使用率将视频处理速度提高 5 倍(教程含源码)
  • python获取文件夹下所有图片目录
  • 【MySQL】慢SQL搜集工具、SQL脱敏聚合处理
  • 手机号发验证码实现用户注册登录
  • 程序员缺乏经验的 7 种表现,你中了几个?
  • Spring框架中的核心技术之AOP
  • 用户体验与响应式字体二三事|rem单位与flexible.js、rpx单位与css媒体查询
  • 408 | 【2009年】计算机统考真题 自用回顾知识点整理
  • MyMusic 重点实现
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • dva中组件的懒加载
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • js正则,这点儿就够用了
  • Phpstorm怎样批量删除空行?
  • React系列之 Redux 架构模式
  • React中的“虫洞”——Context
  • Sublime Text 2/3 绑定Eclipse快捷键
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 汉诺塔算法
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 力扣(LeetCode)357
  • 聊聊directory traversal attack
  • 前端相关框架总和
  • 前嗅ForeSpider教程:创建模板
  • 如何优雅地使用 Sublime Text
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • 一天一个设计模式之JS实现——适配器模式
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • 最简单的无缝轮播
  • 如何用纯 CSS 创作一个货车 loader
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • #Z0458. 树的中心2
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (八)五种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (接口封装)
  • (考研湖科大教书匠计算机网络)第一章概述-第五节1:计算机网络体系结构之分层思想和举例
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (转) Face-Resources
  • (转)Sublime Text3配置Lua运行环境
  • .Net FrameWork总结
  • .net oracle 连接超时_Mysql连接数据库异常汇总【必收藏】
  • .NET 使用 XPath 来读写 XML 文件
  • .net开发时的诡异问题,button的onclick事件无效
  • /var/spool/postfix/maildrop 下有大量文件
  • [ C++ ] 继承
  • [2024] 十大免费电脑数据恢复软件——轻松恢复电脑上已删除文件