zoukankan      html  css  js  c++  java
  • 大数据量分批执行封装

    1. 大数据量分批执行封装

    1.1. 前言

    在执行定时任务的时候,我们常常会有这样的需求,当数据量越来越大,可能你一次查询的数据就会导致内存溢出,所以我们后期往往又要再不断优化,比如分批处理,但分页以后代码量往往呈直线上升,且结构混乱更加复杂难懂,对此我就想写个封装方法,解决任何的分批数据库查询

    1.2. 思路

    事实上,分页等操作都是固定套路,我们只需要把查询整体数据及页数,还有如何处理每一批数据抽象出来即可

    1.3. 实现

    1. 封装了一个静态方法工具(依赖Mybatis
    import com.github.pagehelper.Page;
    import com.github.pagehelper.PageHelper;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.util.StopWatch;
    
    import java.util.List;
    import java.util.function.Consumer;
    import java.util.function.Supplier;
    
    /**
     * @author: laoliangliang
     * @description: 批量执行工具
     * @create: 2020/6/29 9:52
     **/
    @Slf4j
    public class BatchUtil {
    
        /**
         * @param supplier 获取总数据
         * @param consumer 消费分数据
         */
        public static <T> void execute(Supplier<List<T>> supplier, Consumer<List<T>> consumer) {
            execute(supplier, consumer, 1000);
        }
    
        public static <T> void execute(Supplier<List<T>> supplier, Consumer<List<T>> consumer, int pageSize) {
            StopWatch stopWatch = new StopWatch();
            stopWatch.start();
            boolean first = true;
            long total = 1;
            for (int i = 0; i < total; i++) {
                Page<Object> objects = PageHelper.startPage(i + 1, pageSize);
                if (!first) {
                    objects.setCount(false);
                }
                List<T> list = supplier.get();
                if (first) {
                    total = objects.getPages();
                    first = false;
                }
                consumer.accept(list);
            }
            stopWatch.stop();
            log.info("耗时:{}秒", stopWatch.getTotalTimeSeconds());
        }
    }
    
    1. 使用举例,第一个参数写查询所有数据的sql(方法内会做分页),第二个参数即第一个参数的返回结果处理,比如我这里更新一个字段,第三个参数为可选项,分批查询每次查几条
        @Test
        public void updateUserNos() {
            BatchUtil.execute(()-> userMapper.selectAll(), users->{
                for (User user : users) {
                    User userUpdate = new User();
                    userUpdate.setId(user.getId());
                    userUpdate.setUserNo(MD5Util.getUserNo(user.getPhone()));
                    userMapper.updateByPrimaryKeySelective(user);
                }
            },10000);
        }
    

    1.4. 总结

    抽象这样的工具方法,用Java8的lambda表达式,可以节省大量代码,且不用费心思创建类给它取名字,还是很好用的

  • 相关阅读:
    杂记
    [POI2015]PUS
    CF786B Legacy(线段树优化建图)
    SP11470 TTM
    [WC2010]重建计划
    [HNOI2014]世界树
    luogu P4842 城市旅行
    [SDOI2016]征途
    [APIO2014]序列分割
    上下界网络流构图证明
  • 原文地址:https://www.cnblogs.com/sky-chen/p/13207693.html
Copyright © 2011-2022 走看看