用mybatis批处理, 编程式事务,CompletableFuture异步处理,多线程,线程池,list 分页,实现多张表大批量插入

2023-11-09

目录

  1. 概述
  2. 准备工作
  3. 创建数据库表
  4. 创建Java实体类
  5. 创建MyBatis映射文件和DAO接口
  6. 编写Java代码实现多张表大批量插入的功能
  7. 总结

1. 概述

在实际的开发中,我们经常需要将大量的数据插入到数据库中。如果使用单条插入的方式,会导致数据库连接频繁的开启和关闭,从而导致程序性能低下。为了提高程序的性能,我们可以使用批处理的方式来插入数据。同时,我们还可以使用Java编程式事务、多线程、线程池、List分页等技术来实现多张表大批量插入的功能。

本文将介绍如何使用Java编程式事务、多线程、线程池、List分页等技术实现多张表大批量插入的功能。

2. 准备工作

在开始之前,我们需要准备好以下工具和环境:

  • JDK 1.8或以上版本
  • Maven 3.0或以上版本
  • MySQL 5.7或以上版本
  • MyBatis 3.5.7或以上版本

3. 创建数据库表

我们首先需要创建数据库表,以便在后续的实现中使用。假设我们需要向以下两张表中插入数据:

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `product_name` varchar(50) DEFAULT NULL,
  `price` decimal(10,2) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`),
  CONSTRAINT `order_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

4. 创建Java实体类

我们需要创建Java实体类,以便在后续的实现中使用。假设我们需要向以上两张表中插入数据,我们可以创建以下两个Java实体类:

public class User {
    private Integer id;
    private String name;
    private Integer age;
    // 省略getter和setter方法
}

public class Order {
    private Integer id;
    private Integer userId;
    private String productName;
    private BigDecimal price;
    // 省略getter和setter方法
}

5. 创建MyBatis映射文件和DAO接口

我们需要创建MyBatis映射文件和DAO接口,以便在后续的实现中使用。假设我们需要向以上两张表中插入数据,我们可以创建以下两个MyBatis映射文件:

UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
    <insert id="insertBatch" parameterType="java.util.List">
        INSERT INTO `user` (`name`, `age`)
        VALUES
        <foreach collection="list" item="item" index="index" separator=",">
            (#{item.name}, #{item.age})
        </foreach>
    </insert>
</mapper>

OrderMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.OrderMapper">
    <insert id="insertBatch" parameterType="java.util.List">
        INSERT INTO `order` (`user_id`, `product_name`, `price`)
        VALUES
        <foreach collection="list" item="item" index="index" separator=",">
            (#{item.userId}, #{item.productName}, #{item.price})
        </foreach>
    </insert>
</mapper>

然后我们需要创建对应的DAO接口:

public interface UserMapper {
    void insertBatch(List<User> userList);
}

public interface OrderMapper {
    void insertBatch(List<Order> orderList);
}

6. 编写Java代码实现多张表大批量插入的功能

我们可以使用Java编程式事务、多线程、线程池、List分页等技术来实现多张表大批量插入的功能。具体实现步骤如下:

  1. 将数据按照每页大小分割成多个List;
  2. 使用线程池和CompletableFuture异步处理每个List;
  3. 在每个线程中开启事务,将数据批量插入到数据库中;
  4. 如果有任何一个线程的事务失败,回滚所有线程的事务。

以下是示例代码:

@Service
public class BatchInsertService {

    private static final int PAGE_SIZE = 1000;

    private final UserMapper userMapper;
    private final OrderMapper orderMapper;
    private final ThreadPoolTaskExecutor executor;

    public BatchInsertService(UserMapper userMapper, OrderMapper orderMapper, ThreadPoolTaskExecutor executor) {
        this.userMapper = userMapper;
        this.orderMapper = orderMapper;
        this.executor = executor;
    }

    public void batchInsert(List<User> userList, List<Order> orderList) {
        List<List<User>> userPages = splitList(userList, PAGE_SIZE);
        List<List<Order>> orderPages = splitList(orderList, PAGE_SIZE);

        List<CompletableFuture<Void>> futures = new ArrayList<>();

        for (int i = 0; i < userPages.size(); i++) {
            List<User> page = userPages.get(i);
            int index = i;
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    TransactionTemplate transactionTemplate = new TransactionTemplate();
                    transactionTemplate.executeWithoutResult(status -> {
                        userMapper.insertBatch(page);
                    });
                } catch (Exception e) {
                    throw new RuntimeException("Failed to insert users in page " + index, e);
                }
            }, executor);
            futures.add(future);
        }

        for (int i = 0; i < orderPages.size(); i++) {
            List<Order> page = orderPages.get(i);
            int index = i;
            CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                try {
                    TransactionTemplate transactionTemplate = new TransactionTemplate();
                    transactionTemplate.executeWithoutResult(status -> {
                        orderMapper.insertBatch(page);
                    });
                } catch (Exception e) {
                    throw new RuntimeException("Failed to insert orders in page " + index, e);
                }
            }, executor);
            futures.add(future);
        }

        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
    }

    private <T> List<List<T>> splitList(List<T> list, int pageSize) {
        List<List<T>> pages = new ArrayList<>();
        int size = list.size();
        int pageCount = (size + pageSize - 1) / pageSize;
        for (int i = 0; i < pageCount; i++) {
            int fromIndex = i * pageSize;
            int toIndex = Math.min((i + 1) * pageSize, size);
            List<T> page = list.subList(fromIndex, toIndex);
            pages.add(page);
        }
        return pages;
    }
}

在上面的代码中,我们首先将数据按照每页大小分割成多个List,然后使用线程池和CompletableFuture异步处理每个List。在每个线程中,我们使用TransactionTemplate来开启事务,将数据批量插入到数据库中。如果有任何一个线程的事务失败,我们会回滚所有线程的事务。

7. 总结

本文介绍了如何使用Java编程式事务、多线程、线程池、List分页等技术实现多张表大批量插入的功能。具体实现步骤包括创建数据库表、Java实体类、MyBatis映射文件和DAO接口,以及编写Java代码实现多张表大批量插入的功能。通过使用这些技术,我们可以提高程序的性能,减少数据库连接池的压力。在实现过程中,我们还介绍了如何使用编程式事务来保证数据的一致性,以及如何使用线程池和分页技术来提高程序的效率。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用mybatis批处理, 编程式事务,CompletableFuture异步处理,多线程,线程池,list 分页,实现多张表大批量插入 的相关文章

  • 从 java sdk 向对等方发送提案时出现访问被拒绝错误

    我正在尝试使用以下代码查询区块链并收到访问被拒绝错误 我也遇到同样的错误sendTransactionProposal方法也是如此 UserContext adminUserContext RegisterEnrollUser regist
  • 存根方法时出现 InvalidUseOfMatchersException

    我有这个 TestNG 测试方法代码 InjectMocks private FilmeService filmeService new FilmeServiceImpl Mock private FilmeDAO filmeDao Bef
  • 如何将画廊意图中的“打开”更改为“完成”?

    我使用以下意图打开画廊来选择多个图像和视频 Intent intent new Intent intent setType image video intent putExtra Intent EXTRA ALLOW MULTIPLE tr
  • Java:无法从同一包中的不同类访问静态变量

    这很奇怪 因为我有一个可以访问 Frame dimension getWidth 的 Character 类 及其伙伴 getHeight 但是当我想在 Map 类中使用它时 Eclipse 强调了它并且无法给我反馈 运行该程序最终会出现
  • GWT - 如何组织项目以拥有多个网页以及它们之间的导航

    我是 GET 的新手 顺便说一句 它给我留下了深刻的印象 并且发现它对于像我这样熟悉 C NET 桌面技术并愿意编写 Web 应用程序的人来说非常有吸引力 我根据 GWT Eclipse 向导生成的示例启动了自己的项目 该项目生成带有面板的
  • 通往楼梯顶部的可能路径

    这是一个非常经典的问题 我听说谷歌在他们的面试中使用过这个问题 问题 制定一个递归方法 打印从楼梯底部到楼梯顶部的所有可能的独特路径 有 n 个楼梯 您一次只能走 1 步或 2 步 示例输出 如果它是一个有 3 级楼梯的楼梯 1 1 1 2
  • 在 Wildfly 中与 war 部署共享 util jar 文件

    假设我有一个名为 util jar 的 jar 文件 该 jar 文件主要包含 JPA 实体和一些 util 类 无 EJB 如何使这个 jar 可用于 Wildfly 中部署的所有 war 无需将 jar 放置在 war 的 WEB IN
  • 如何将 Mat (opencv) 转换为 INDArray (DL4J)?

    我希望任何人都可以帮助我解决这个任务 我正在处理一些图像分类并尝试将 OpenCv 3 2 0 和 DL4J 结合起来 我知道DL4J也包含Opencv 但我认为它没什么用 谁能帮我 如何转换成 INDArray 我尝试阅读一些问题here
  • 什么时候可以在 Java 中使用 Thead.stop() ?

    Thread stop 的 Java 文档听起来好像如果您调用 Thread stop 世界就会终结 已弃用 这种方法本质上是不安全的 停止线程 Thread stop 导致它解锁所有已锁定的监视器 作为未经检查的 ThreadDeath
  • 如何检测 Java 字符串中的 unicode 字符?

    假设我有一个包含 的字符串 我如何找到所有这些 un icode 字符 我应该测试他们的代码吗 我该怎么做呢 例如 给定字符串 A X 我想将其转换为 AYXY 我想对其他 unicode 字符做同样的事情 并且我不想将它们存储在某种翻译映
  • 使用 Guice 优化注册表

    你好 今天思考了一种优化 有一些疑问 语境 我正在使用 Guice 2 进行 Java 开发 在我的网络应用程序中 我有一个转换器注册表 可以即时转换为某种类型 转换器描述如下 public class StringToBoolean im
  • 生成的序列以 1 开头,而不是注释中设置的 1000

    我想请求一些有关 Hibernate 创建的数据库序列的帮助 我有这个注释 下面的代码 在我的实体类中 以便为合作伙伴表提供单独的序列 我希望序列以 1000 开头 因为我在部署期间使用 import sql 将测试数据插入数据库 并且我希
  • 如何避免 ArrayIndexOutOfBoundsException 或 IndexOutOfBoundsException? [复制]

    这个问题在这里已经有答案了 如果你的问题是我得到了java lang ArrayIndexOutOfBoundsException在我的代码中 我不明白为什么会发生这种情况 这意味着什么以及如何避免它 这应该是最全面的典范 https me
  • 流中的非终结符 forEach() ?

    有时 在处理 Java Stream 时 我发现自己需要一个非终端 forEach 来触发副作用但不终止处理 我怀疑我可以用 map item gt f item 之类的方法来做到这一点 其中方法 f 执行副作用并将项目返回到流中 但这似乎
  • 在 SWT/JFace RCP 应用程序中填充巨大的表

    您将如何在 SWT 表中显示大量行 巨大是指超过 20K 行 20 列的东西 不要问我为什么需要展示那么多数据 这不是重点 关键是如何让它尽可能快地工作 这样最终用户就不会厌倦等待 每行显示某个对象的实例 列是其属性 一些 我想使用 JFa
  • Docker 和 Eureka 与 Spring Boot 无法注册客户端

    我有一个使用 Spring Boot Docker Compose Eureka 的非常简单的演示 我的服务器在端口 8671 上运行 具有以下应用程序属性 server port 8761 eureka instance prefer i
  • Resteasy 可以查看 JAX-RS 方法的参数类型吗?

    我们使用 Resteasy 3 0 9 作为 JAX RS Web 服务 最近切换到 3 0 19 我们开始看到很多RESTEASY002142 Multiple resource methods match request警告 例如 我们
  • OpenCSV:将嵌套 Bean 映射到 CSV 文件

    我正在尝试将 bean 映射到 CSV 文件 但问题是我的 bean 具有其他嵌套 bean 作为属性 所发生的情况是 OpenCSV 遍历属性找到一个 bean 然后进入其中并映射该 bean 内的所有数据 如果找到另一个 bean 它就
  • 如何重新启动死线程? [复制]

    这个问题在这里已经有答案了 有哪些不同的可能性可以带来死线程回到可运行状态 如果您查看线程生命周期图像 就会发现一旦线程终止 您就无法返回到新位置 So 没有办法将死线程恢复到可运行状态 相反 您应该创建一个新的 Thread 实例
  • 泛型、数组和 ClassCastException

    我想这里一定发生了一些我不知道的微妙事情 考虑以下 public class Foo

随机推荐

  • Go GPM 调度器介绍

    Go GPM 调度器介绍 1 简介 这几天在学习Go的GPM机制 于是就整理了一下收集的资料分享给大家 文章末尾有原文链接 主要介绍了Go在运行时调度器的基本实现逻辑和演变过程 2 什么是Go调度器 Go调度器很轻量也很简单 足以撑起gor
  • ☀️光学会自动化测试还不够?还差最后这一步!☀️

    同大多数项目一样 自动化测试项目也需要一个完整的项目管理流程 在项目执行之前要进行充分的评估和计划 项目执行过程中要把控每个节点的质量 执行后要进行复盘和评估 确保项目顺利实施 并达到预期效果 01 自动化项目启动 在项目启动阶段 我们要明
  • cmd 字符串拼接

    在 Windows 系统的 cmd 或 PowerShell 中 可以使用 来拼接字符串 例如 echo 我的名字是 amp echo 小明
  • 10 个实用功能告诉你,谷歌云(Google Cloud)相对亚马逊云(AWS)有哪些优势?...

    来源 itnext 编译 武明利 责编 Carol 出品 CSDN云计算 ID CSDNcloud 有很多文章将谷歌云提供商 GCP 与亚马逊云服务 AWS 进行比较 但这篇文章并不想要做比较 作者主要是一个AWS用户 但最近一直使用GCP
  • LeetCode198.打家劫舍(动态规划)

    题目描述 来自LeetCode 思路 这道题和01背包很像 这件房屋偷不偷跟前一间房屋是否偷了有关 比如说这是第i间房屋 如果第i 1间房屋偷了 那第i间房屋就不能再偷 那最大值就跟前i 1间房屋的金额最大值有关 如果第i 1间房屋没偷 那
  • hp linux 禁用u盘启动,BIOS关闭Secure Boot(安全启动)方法大全(联想,华硕,DELL,HP等品牌)...

    在预装win10系统的电脑上BIOS中安全启动Secure Boot是默认开启的 如果你要安装其他系统 如Win7 Linux等系统那么需要关闭才可以 不然会无启动 这小编整理了联想 华硕 DELL HP等品牌关闭Secure Boot 安
  • 斗罗大陆解算法—魂环的最佳获取法

    前言 作者主页 雪碧有白泡泡 个人网站 雪碧的个人网站 推荐专栏 java一站式服务 前端炫酷代码分享 uniapp 从构建到提升 从0到英雄 vue成神之路 解决算法 一个专栏就够了 架构咱们从0说 数据流通的精妙之道 文章目录 前言 背
  • 关于kettle的一些使用笔记

    Kettle是一款国外开源的ETL工具 纯java编写 对于办公自动化来说也是一款神器 好了直入主题 这里只记录了kettle的一些常用的转换的组件作用和意义 并不含软件安装和使用过程 因为这个过程很简单 界面很友好 可以自己摸索 vers
  • Android9.0 iptables用INetd实现ip白名单的实现

    1 前言 在9 0的系统rom定制化开发中 在system中netd网络这块的产品需要中 会要求设置屏蔽ip地址之内的功能 liunx中iptables命令也是比较重要的 接下来就来在INetd这块实现ip白名单的的相关功能 就是在app中
  • 理解Linux下的进程和程序,分析fork、execve和进程切换

    本次实验从整体上理解进程创建 可执行文件的加载和进程执行进程切换 重点理解分析fork execve和进程切换 一 理解task struct数据结构 进程是处于执行期的程序以及它所管理的资源 如打开的文件 挂起的信号 进程状态 地址空间等
  • 经理人必看的十个管理网站

    经理人必看的十个管理网站 管理这玩艺远远看着如同象牙塔中的佛牙舍利 可观而不可玩 其实身在其中无非就是一张窗户纸 没有什么大不了的 管理这玩艺远远看着如同象牙塔中的佛牙舍利 可观而不可玩 其实身在其中无非就是一张窗户纸 没有什么大不了的 网
  • C# NPOI写excel文件,设置某个单元格为自动筛选

    https blog csdn net qq 40467670 article details 118102078 如标题所示 附上几行代码 HSSFWorkbook workbook new HSSFWorkbook 创建工作表 var
  • Uva 10474 Where is the Marble?(排序与检索)

    本题若掌握了sort 和lower bound 两个函数 就无难点 include
  • 通关6级之词汇(2021.05.29)

    前言 这篇词汇是通关6级系列第一篇文章 这篇文章和4级有大部分内容是一样的 所以如果学了4级的课程再学这个会很轻松 更多相关文章点击阅读 通关4级之阅读理解 通关4级之听力 通关4级之写作 通关4级之翻译 通关4级之词汇 通关6级之词汇 点
  • STM32 ST-LINK Utility程序烧录方法

    打开软件过后点击Target connect 出现以下界面表示STlink链接成功 如果出现没有检测到stlink的话 首先查看是否安装驱动程序 再重新插拔电脑usb口的stlink连接线 或者链接到主机后方的usb口 再重复以上步骤链接
  • Fire Net

    点击打开链接 Problem Description Suppose that we have a square city with straight streets A map of a city is a square board wi
  • 利用python对b站某GPT-4解说视频的近万条弹幕进行爬取、数据挖掘、数据分析、弹幕数量预测及情绪分类

    目录 一 利用Python爬取弹幕 二 利用几行代码直接生成词云 三 将弹幕属性和内容放入mysql当中 四 分析弹幕在视频各节点的数量 1 分析视频各个片段出现的弹幕数量 2 分析视频各大章节出现的弹幕数量 3 分析视频各小节出现的弹幕数
  • Learning Java language Fundamentals

    Chapter 2 Learning Java language fundamentals exercises 1 What is Unicode Unicode is a computing industry standard for c
  • 炒股新手技巧

    技巧一 关于止损和止赢的问题 我觉得很重要 止赢和止损的设置对股民来说尤为重要 有很多散户会设立止损 但是不会止赢 今天有必要和大家探讨一下 止损的设立大家都知道 设定一个固定的亏损率 到达位置严格执行 但是止赢 一般的散户都不会 为什么说
  • 用mybatis批处理, 编程式事务,CompletableFuture异步处理,多线程,线程池,list 分页,实现多张表大批量插入

    目录 概述 准备工作 创建数据库表 创建Java实体类 创建MyBatis映射文件和DAO接口 编写Java代码实现多张表大批量插入的功能 总结 1 概述 在实际的开发中 我们经常需要将大量的数据插入到数据库中 如果使用单条插入的方式 会导