分批查询SQL

1. 背景

批量查询,如何入参数组参数过多,会导致SQL长度过长,数据库会拒绝查询

2. 解决方式

在代码的层面上,进行分批查询,例如2000个参数,分成1000一批来进行查询,但是又会有几个问题

  1. 不同类的查询,入参和出参均不同,有没有一种方式,可以兼容不同的出入参
  2. 全量查询sql会去重,分批查询,不同批次会查出重复的数据,如何去重

3. 编程代码

通过函数式编程,封装函数,根据不同的查询,传入不同的查询类,就不用每个方式单独写一次

新建函数式函数式接口

@FunctionalInterface
public interface DatabaseOperation<T, R> {

    /**
     * 分批操作
     *
     * @param partition
     * @return
     */
    R apply(List<T> partition);
}

封装函数

    /**
     * 分批次操作(增、删、改、查),最后合并结果 解决2048 问题,
     *
     * @param inputList 所有查询的列表
     * @param maxSize 分割数
     * @param operation mapper查询操作
     * @param distinctByKey 唯一值,用于去重,避免分批查询合并得结果有重复数据
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> List<R> executeInPartitions(List<T> inputList, int maxSize,
                                                     DatabaseOperation<T, List<R>> operation,
                                                     Function<? super R, ?> distinctByKey) {
        // 使用LinkedHashMap保留插入顺序,在去重时将会用到
        Map<Object, R> map = new LinkedHashMap<>();

        if (inputList == null || inputList.isEmpty()) {
            return new ArrayList<>(map.values());
        }
        // 将输入列表根据最大大小切割并执行操作
        for (int i = 0; i < inputList.size(); i += maxSize) {
            int end = Math.min(inputList.size(), i + maxSize);
            List<T> partition = inputList.subList(i, end);
            // 对每个分区执行数据库操作
            List<R> result = operation.apply(partition);
            if (result != null) {
                // 根据提供的键提取器去重并收集结果
                result.stream()
                        .collect(Collectors.toMap(distinctByKey, r -> r,
                                (existing, replacement) -> existing, LinkedHashMap::new))
                        .forEach((key, value) -> map.putIfAbsent(key, value));
            }
        }
        return new ArrayList<>(map.values());
    }

使用方式

List<Person> baseInfoList = ListUtils.executeInPartitions(personList, 1000,
                partition -> personMapper.getPerson(partition), Person::getId);
posted @   God-slayer  阅读(83)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示