首页 > 编程语言 >编程日记 批量导入数据

编程日记 批量导入数据

时间:2024-09-15 21:46:00浏览次数:1  
标签:批量 编程 List userList 导入 CompletableFuture user stopWatch new

编程日记 批量导入数据

1.用可视化界面:适合一次性导入,数据量可控

2.写程序:for循环,建议分批,不要一把梭哈(可以用接口控制),要保证可控、幂等,注意线上环境和测试环境是有区别的

导入1000w条,for i 1000w

(不能再main方法里面写,会报空指针异常,userMapper无法注入)

缺点是.class并不是一个spring的bean,他没有被spring托管,无法使用@resounces注解

3.执行SQL语句,适用于小数据量

编写一次性任务

for循环插入数据的问题:

​ 1.建立和释放数据库链接(批量查询解决)

@Resource
    private UserService userService;

    /**
     * 批量插入用户
     */
    @Test
    //fixedDelay就是每隔5s执行一次
    public void doInsertUsers() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        final int INSERT_NUM = 100000;
        List<User> userList = new ArrayList<>();
        for (int i = 0; i < INSERT_NUM; i++) {
            User user = new User();
            user.setUsername("原_创 【鱼_皮】https://t.zsxq.com/0emozsIJh");
            user.setUserAccount("fakeyupi");
            user.setAvatarUrl("https://636f-codenav-8grj8px727565176-1256524210.tcb.qcloud.la/img/logo.png");
            user.setGender(0);
            user.setUserPassword("12345678");
            user.setPhone("123");
            user.setEmail("[email protected]");
            user.setTags("[]");
            user.setUserStatus(0);
            user.setUserRole(0);
            user.setPlanetCode("11111111");
            userList.add(user);
        }
        // 20 秒 10 万条
        userService.saveBatch(userList, 1000);
        stopWatch.stop();
        System.out.println(stopWatch.getTotalTimeMillis());
    }

​ 2.for循环是绝对线性的(并发)

并发要注意执行的先后顺序无所谓

@Resource
    private UserService userService;
    /**
     * 并发批量插入用户
     */
@Test
    public void doConcurrencyInsertUsers() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        // 分十组
        int batchSize = 5000;
        int j = 0;
        List<CompletableFuture<Void>> futureList = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            List<User> userList = new ArrayList<>();
            while (true) {
                j++;
                User user = new User();
                user.setUsername("假鱼皮");
                user.setUserAccount("fakeyupi");
                user.setAvatarUrl("https://636f-codenav-8grj8px727565176-1256524210.tcb.qcloud.la/img/logo.png");
                user.setGender(0);
                user.setUserPassword("12345678");
                user.setPhone("123");
                user.setEmail("[email protected]");
                user.setTags("[]");
                user.setUserStatus(0);
                user.setUserRole(0);
                user.setPlanetCode("11111111");
                userList.add(user);
                if (j % batchSize == 0) {
                    break;
                }
            }
            // 异步执行
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                System.out.println("threadName: " + Thread.currentThread().getName());
                userService.saveBatch(userList, batchSize);
            }, executorService);
            futureList.add(future);
        }
        
        CompletableFuture.allOf(futureList.toArray(new CompletableFuture[]{})).join();
        // 20 秒 10 万条
        stopWatch.stop();
        System.out.println(stopWatch.getTotalTimeMillis());
    }

注意第38行代码:

这段代码是使用Java的CompletableFuture类来等待一组CompletableFuture对象全部执行完毕。

CompletableFuture.allOf(...),是一个静态方法,它接收一个CompletableFuture数组作为参数,并返回一个新的CompletableFuture对象。这个新的CompletableFuture对象会在参数中所有的CompletableFuture对象都执行完毕之后完成,即它会等待传入的所有CompletableFuture对象完成,才会执行下一条语句。

array.toArray(new CompletableFuture[]{}),这段代码是将一个List集合(array)转换成一个数组,并作为参数传递给CompletableFuture.allOf()方法。这是通过将List集合转换为一个空的CompletableFuture数组来实现的。

.join(),是CompletableFuture对象的一个方法,会阻塞当前线程,直到该CompletableFuture对象完成,并返回对象的结果值。

此代码CompletableFuture.allOf(array.toArray(new CompletableFuture[]{})).join()的意思是等待List集合(array)中的所有CompletableFuture对象都执行完毕,并阻塞当前线程直到所有CompletableFuture对象都完成。

标签:批量,编程,List,userList,导入,CompletableFuture,user,stopWatch,new
From: https://www.cnblogs.com/vastjoy/p/18415707

相关文章

  • 编程日记 后端使用redis
    编程日记后端使用redis问题:在写伙伴匹配系统的时候,要使用redis存储数据,需要在xml文件中设置spring.session.tore-type=redis但是3.x版本的spring不再有这个参数。那么怎么设置是否使用redis存储呢?只要导入了org.springframework.session包那就启用,不导入就不启用https://www.......
  • 带你0到1之QT编程:十二、视图宝典,点通views的任督二脉
    此为QT编程的第十二谈!关注我,带你快速学习QT编程的学习路线!每一篇的技术点都是很很重要!很重要!很重要!但不冗余!我们通常采取总-分-总和生活化的讲解方式来阐述一个知识点!码农不易,各位学者学到东西请点赞支持支持!开始部分:总:view视图组:QListView、QTreeView、TableView、QLi......
  • Day10.面向对象编程OOP(2)
    封装该露的露,该藏的藏高内聚,低耦合:高内聚:类的内部数据操作细节自己完成,不允许外部干涉低耦合:仅暴露少量的方法给外部使用提高程序的安全性,保护数据隐藏代码的实现细节统一接口提高系统的可维护性packagecom.dongfang.oop.Demo04;//类publicclassDemo01......
  • Vue框架;Vue中的选择和循环结构;Vue数据类型;Vue中的事件和动态属性;Vue子组件通过导入在
    一,Vue简介        前端现在比较火的三大框架就是:vue,React,Angular。在国内使用最多的还是:    vue>React >Angular        Vue(发音为/vjuː/,类似view)是一款用于构建用户界面的JavaScript框架。它基于标准HTML、CSS和JavaScript构建,并提......
  • mysql数据怎么导入到帝国cms
    将MySQL数据导入到帝国CMS中通常有两种情况:一种是从现有的MySQL数据库导入数据到帝国CMS的新建数据库中,另一种是从帝国CMS的备份文件恢复数据到现有的帝国CMS数据库中。以下是针对这两种情况的具体步骤:从现有MySQL数据库导入数据到帝国CMS方法一:手动迁移数据导出现有数据库:......
  • chapter08 面向对象编程高级 知识点总结Note
    文章目录static修饰符单例设计模式main()方法类的成员代码块实例变量赋值位置顺序final关键字abstract关键字使用抽象应用模板方法设计接口语法应用(多态匿名实现类)jdk8jdk9接口新特性类的成员内部类枚举类(自定义enum方法实现接口)注解常用注解与JUnit单元测试......
  • windows C++ 并行编程-并行容器和对象
    并行模式库(PPL)包括几个容器和对象,这些容器和对象提供对其元素的线程安全访问。并发容器提供对最重要操作的并发安全访问。在这里,并发安全意味着指针或迭代器始终有效。它不保证元素初始化或特定的遍历顺序。这些容器的功能与C++标准库提供的功能类似。例如,concurren......
  • windows C++-并行编程-PPL任务并行(一)
    在并发运行时中,任务是执行特定作业并通常与其他任务并行运行的工作单元。任务可以分解为组织成任务组的其他更细化的任务。编写异步代码,并希望在异步操作完成之后进行某种操作时,可使用任务。例如,可以使用一个任务以异步方式从文件读取,然后使用另一个任务(延续任务,本文档稍后......
  • Nuxt Kit 组件管理:注册与自动导入
    title:NuxtKit组件管理:注册与自动导入date:2024/9/15updated:2024/9/15author:cmdragonexcerpt:NuxtKit为组件的注册和导入提供了灵活高效的解决方案。无论你是要批量导入组件,还是单独处理特定组件,这些工具都能够满足你的需求。使用这些方法可以显著提升开发效率......
  • C#编程中的贪心策略:找零钱问题
    C#中的贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法。贪心算法并不保证总是能得到全局最优解,但它通常实现简单,且对于很多问题来说,其解是足够好的,或者可以证明贪心选择能导致全局最优解。下面是一个使......