Mybatis-Plus大批量插入数据到MySQL

MyBatis-Plus的saveBatch方法

@GetMapping("/save1")
public void save1() {// 数据准备List<MallOrder> orderList = getMallOrderList();// mybatis-pluslong start = System.currentTimeMillis();mallOrderService.saveBatch(orderList);System.out.println("mybatis-plus的【savaBatch】插入数据,耗时:" + (System.currentTimeMillis() - start) + "ms");
}

MyBatis-Plus的xml方式

@GetMapping("/save2")
public void save2() {// 数据准备List<MallOrder> orderList = getMallOrderList();// xmllong start = System.currentTimeMillis();mallOrderService.saveBatchXml(orderList);System.out.println("mybatis-plus的【xml拼接sql】插入数据,耗时:" + (System.currentTimeMillis() - start) + "ms");
}
<insert id="saveBatch">insert into mall_order (order_id,customer_id,order_status,payment_method,total_amount,shipping_fee,coupon_discount,order_date,payment_time,shipping_address,receiver_name,receiver_phone)values<foreach collection="orderList" item="item" separator=",">(#{item.orderId},#{item.customerId},#{item.orderStatus},#{item.paymentMethod},#{item.totalAmount},#{item.shippingFee},#{item.couponDiscount},#{item.orderDate},#{item.paymentTime},#{item.shippingAddress},#{item.receiverName},#{item.receiverPhone})</foreach>
</insert>

MyBatis-Plus的批量插入器

@GetMapping("/save3")
public void save3() {// 数据准备List<MallOrder> orderList = getMallOrderList();// insertBatchSomeColumnlong start = System.currentTimeMillis();mallOrderService.insertBatchSomeColumn(orderList);System.out.println("mybatis-plus的【insertBatchSomeColumn】插入数据,耗时:" + (System.currentTimeMillis() - start) + "ms");
}
package com.qiangesoft.batchsave.config;import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;import java.util.List;/*** sql注入器** @author qiangesoft* @date 2024-04-11*/
public class InsertBatchSqlInjector extends DefaultSqlInjector {@Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {// super.getMethodList() 保留 Mybatis Plus 自带的方法List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);// 添加自定义方法:批量插入,方法名为 insertBatchSomeColumn// bean mapper中的方法名也是insertBatchSomeColumn 须和内部定义好的方法名保持一致。methodList.add(new InsertBatchSomeColumn());return methodList;}}
package com.qiangesoft.batchsave.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** mybatis-plus配置** @author qiangesoft* @date 2024-04-11*/
@Configuration
public class MybatisPlusConfig {@Beanpublic InsertBatchSqlInjector insertBatchSqlInjector() {return new InsertBatchSqlInjector();}}
package com.qiangesoft.batchsave.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qiangesoft.batchsave.entity.MallOrder;
import org.apache.ibatis.annotations.Param;import java.util.List;/*** <p>* 订单信息表 Mapper 接口* </p>** @author qiangesoft* @since 2024-05-07*/
public interface MallOrderMapper extends BaseMapper<MallOrder> {/*** 批量插入 仅适用于mysql** @param orderList*/Integer insertBatchSomeColumn(List<MallOrder> orderList);
}

SqlSession手动提交

@GetMapping("/save4")
public void save4() {// 数据准备List<MallOrder> orderList = getMallOrderList();// 手动提交long start = System.currentTimeMillis();mallOrderService.manualCommit(orderList);System.out.println("sqlSession的【手动提交】插入数据100000条,耗时:" + (System.currentTimeMillis() - start) + "ms");
}
@Autowired
private SqlSessionFactory sqlSessionFactory;@Override
public void manualCommit(List<MallOrder> orderList) {// 关闭自动提交SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);MallOrderMapper mallOrderMapper = sqlSession.getMapper(MallOrderMapper.class);for (MallOrder mallOrder : orderList) {mallOrderMapper.insert(mallOrder);}sqlSession.commit();sqlSession.clearCache();sqlSession.close();
}

循环执行MyBatis-Plus的save方法

@GetMapping("/save5")
public void save5() {// 数据准备List<MallOrder> orderList = getMallOrderList();// 循环插入long start = System.currentTimeMillis();for (MallOrder mallOrder : orderList) {mallOrderService.save(mallOrder);}System.out.println("mybatis-plus的【循环】插入数据100000条,耗时:" + (System.currentTimeMillis() - start) + "ms");
}

Statement批量执行

@GetMapping("/save6")
public void save6() {// 数据准备List<MallOrder> orderList = getMallOrderList();// statement.executeBatchlong start = System.currentTimeMillis();mallOrderService.executeBatch(orderList);System.out.println("statement的【executeBatch】插入数据100000条,耗时:" + (System.currentTimeMillis() - start) + "ms");
}
@Override
public void executeBatch(List<MallOrder> orderList) {String sql = "insert into mall_order (" +"customer_id," +"order_status," +"payment_method," +"total_amount," +"shipping_fee," +"coupon_discount," +"order_date," +"payment_time," +"shipping_address," +"receiver_name," +"receiver_phone) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";SqlSession sqlSession = null;Connection connection = null;PreparedStatement statement = null;try {sqlSession = sqlSessionFactory.openSession();connection = sqlSession.getConnection();connection.setAutoCommit(false);statement = connection.prepareStatement(sql);for (MallOrder mallOrder : orderList) {// 主键自增不设置
//                statement.setLong(0, mallOrder.getOrderId());statement.setLong(1, mallOrder.getCustomerId());statement.setInt(2, mallOrder.getOrderStatus());statement.setInt(3, mallOrder.getPaymentMethod());statement.setBigDecimal(4, mallOrder.getTotalAmount());statement.setBigDecimal(5, mallOrder.getShippingFee());statement.setBigDecimal(6, mallOrder.getCouponDiscount());statement.setObject(7, mallOrder.getOrderDate());statement.setObject(8, mallOrder.getPaymentTime());statement.setString(9, mallOrder.getShippingAddress());statement.setString(10, mallOrder.getReceiverName());statement.setString(11, mallOrder.getReceiverPhone());statement.addBatch();}statement.executeBatch();connection.commit();} catch (SQLException e) {throw new RuntimeException(e);} finally {if (statement != null) {try {statement.close();} catch (SQLException e) {throw new RuntimeException(e);}}if (connection != null) {try {connection.close();} catch (SQLException e) {throw new RuntimeException(e);}}if (sqlSession != null) {sqlSession.close();}}
}

MyBatis-Plus的saveBatch方法+异步任务

@GetMapping("/save7")
public void save7() {// 数据准备List<MallOrder> orderList = getMallOrderList();// 异步任务处理long start = System.currentTimeMillis();mallOrderService.saveBatchAsync(orderList);System.out.println("mybatis-plus的【异步任务处理】插入数据100000条,耗时:" + (System.currentTimeMillis() - start) + "ms");
}
@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Autowired
private PlatformTransactionManager transactionManager;@Override
public void saveBatchAsync(List<MallOrder> orderList) {int count = orderList.size();// 每批次插入的数据量int pageSize = 1000;// 线程数int threadNum = count % pageSize == 0 ? (count / pageSize) : (count / pageSize + 1);CountDownLatch countDownLatch = new CountDownLatch(threadNum);for (int i = 0; i < threadNum; i++) {int startIndex = i * pageSize;int endIndex = Math.min(count, (i + 1) * pageSize);List<MallOrder> subList = orderList.subList(startIndex, endIndex);threadPoolTaskExecutor.execute(() -> {DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();TransactionStatus status = transactionManager.getTransaction(transactionDefinition);try {// 保存数据this.saveBatch(subList);transactionManager.commit(status);} catch (Exception exception) {transactionManager.rollback(status);throw exception;} finally {countDownLatch.countDown();}});}try {countDownLatch.await();} catch (InterruptedException e) {throw new RuntimeException(e);}
}

测试

CREATE TABLE `mall_order`
(`order_id`         BIGINT         NOT NULL AUTO_INCREMENT COMMENT '订单ID(主键)',`customer_id`      BIGINT         NOT NULL COMMENT '客户ID(关联customer表)',`order_status`     tinyint(4)     NOT NULL DEFAULT 1 COMMENT '订单状态 1-待支付 2-已支付 3-待发货 4-已发货 5-已完成 6-已取消',`payment_method`   tinyint(4)     NULL     DEFAULT null COMMENT '支付方式; 1-现金 2-支付宝 3-微信 4-银行卡',`total_amount`     DECIMAL(10, 2) NOT NULL COMMENT '订单总金额',`shipping_fee`     DECIMAL(10, 2) NOT NULL DEFAULT 0 COMMENT '运费',`coupon_discount`  DECIMAL(10, 2) NOT NULL DEFAULT 0 COMMENT '优惠券减免金额',`order_date`       DATETIME       NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '下单日期',`payment_time`     DATETIME                DEFAULT NULL COMMENT '支付时间',`shipping_address` VARCHAR(255)   NULL COMMENT '收货地址',`receiver_name`    VARCHAR(50)    NULL COMMENT '收货人姓名',`receiver_phone`   VARCHAR(20)    NULL COMMENT '收货人电话',PRIMARY KEY (`order_id`)
) ENGINE = InnoDBDEFAULT CHARSET = utf8mb4 COMMENT ='订单信息表';
package com.qiangesoft.batchsave.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;/*** <p>* 订单信息表* </p>** @author qiangesoft* @since 2024-05-07*/
@Getter
@Setter
@Accessors(chain = true)
@TableName("mall_order")
public class MallOrder implements Serializable {private static final long serialVersionUID = 1L;/*** 订单ID(主键)*/@TableId(value = "order_id", type = IdType.INPUT)private Long orderId;/*** 客户ID(关联customer表)*/private Long customerId;/*** 订单状态 1-待支付 2-已支付 3-待发货 4-已发货 5-已完成 6-已取消*/private Integer orderStatus;/*** 支付方式; 1-现金 2-支付宝 3-微信 4-银行卡*/private Integer paymentMethod;/*** 订单总金额*/private BigDecimal totalAmount;/*** 运费*/private BigDecimal shippingFee;/*** 优惠券减免金额*/private BigDecimal couponDiscount;/*** 下单日期*/private LocalDateTime orderDate;/*** 支付时间*/private LocalDateTime paymentTime;/*** 收货地址*/private String shippingAddress;/*** 收货人姓名*/private String receiverName;/*** 收货人电话*/private String receiverPhone;}

1000条

/*** 构建数据** @return*/
private static List<MallOrder> getMallOrderList() {List<MallOrder> orderList = new ArrayList<>();for (int i = 0; i < 10000; i++) {MallOrder mallOrder = new MallOrder();mallOrder.setCustomerId(1L);mallOrder.setOrderStatus(1);mallOrder.setPaymentMethod(1);mallOrder.setTotalAmount(BigDecimal.valueOf(12));mallOrder.setShippingFee(BigDecimal.valueOf(1));mallOrder.setCouponDiscount(BigDecimal.valueOf(0));mallOrder.setOrderDate(LocalDateTime.now());mallOrder.setPaymentTime(LocalDateTime.now());mallOrder.setShippingAddress("哈哈");mallOrder.setReceiverName("暂时");mallOrder.setReceiverPhone("13211111111");orderList.add(mallOrder);}return orderList;
}

在这里插入图片描述

10000条

/*** 构建数据** @return*/
private static List<MallOrder> getMallOrderList() {List<MallOrder> orderList = new ArrayList<>();for (int i = 0; i < 1000; i++) {MallOrder mallOrder = new MallOrder();mallOrder.setCustomerId(1L);mallOrder.setOrderStatus(1);mallOrder.setPaymentMethod(1);mallOrder.setTotalAmount(BigDecimal.valueOf(12));mallOrder.setShippingFee(BigDecimal.valueOf(1));mallOrder.setCouponDiscount(BigDecimal.valueOf(0));mallOrder.setOrderDate(LocalDateTime.now());mallOrder.setPaymentTime(LocalDateTime.now());mallOrder.setShippingAddress("哈哈");mallOrder.setReceiverName("暂时");mallOrder.setReceiverPhone("13211111111");orderList.add(mallOrder);}return orderList;
}

在这里插入图片描述

总结

由此可见:
MyBatis-Plus的批量插入器、Statement批量执行、MyBatis-Plus的saveBatch方法+异步任务这三种方式较快。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3015317.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

做私域,朋友圈到底该怎么发?

说到做私域&#xff0c;很多人都会问&#xff1a;朋友圈该怎么发&#xff1f;相信大家的朋友圈早已经被各种广告攻占了&#xff0c;很多也都被大家屏蔽了。但如果要做私域&#xff0c;单纯发广告是行不通的&#xff0c;可是现在依然有很多人&#xff0c;认为做私域就是狂发朋友…

RabbitMQ的介绍和使用

1.同步通讯和异步通讯 举个例子&#xff0c;同步通讯就像是在打电话&#xff0c;因此它时效性较强&#xff0c;可以立即得到结果&#xff0c;但如果你正在和一个MM打电话&#xff0c;其他MM找你的话&#xff0c;你们之间是不能进行消息的传递和响应的 异步通讯就像是微信&#…

美国纽扣电池UL4200A及16CFR1262标准亚马逊要求

2023年9月21日&#xff0c;美国消费品安全委员会CPSC(Consumer Product Safety Commission) 决定采用UL 4200A-2023&#xff08;包含纽扣电池或硬币电池的产品安全标准&#xff09;作为包含纽扣电池或硬币电池的消费品的强制性消费品安全规则&#xff0c;相关要求同时被编入到1…

前端数据可视化基础(折线图)

目录 前言&#xff1a; 画布&#xff1a; 折线图 (Line Chart): 前言&#xff1a; 前端中的数据可视化是指将大量数据以图形或图像的形式在前端页面上展示出来&#xff0c;以便用户能够更直观地理解和分析这些数据。数据可视化是一种强大的工具&#xff0c;它利用了人类视觉…

《架构思维:从程序员到CTO》:通往顶级架构师之路

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

使用excel合理整理数据

使用excel合理整理数据 Excel函数LOOKUP把两个sheet数据关联起来LOOKUP函数 Excel函数LOOKUP把两个sheet数据关联起来 LOOKUP函数 需求场景 1、sheet1是视频的数据比如 aid、作者、视频信息 2、sheet2是视频的播放数据比如 aid vv uv等 做的就是根据1、2 的aid 将 sheet2中的所…

多目标灰狼算法(MOGWO):原理讲解与代码实现 Matlab代码免费获取

声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 目录 原理简介 一、Pareto最优概念 二、单目标G…

高实时、高可靠的微内核操作系统——鸿道Intewell

近年来&#xff0c;我国不断推进工业转型升级&#xff0c;力求实现从传统工业大国向现代工业强国的跨越。想要在新一轮科技革命中“超车”&#xff0c;需要从多个维度进行深度布局和全面发力。 ——科技创新是核心驱动力 积极推动工业结构的优化和升级&#xff0c;通过发展新…

求知导刊-知网收录//旬刊//如何投稿?

求知导刊-知网收录//旬刊//如何投稿&#xff1f; 《求知导刊》栏目设置 理论探索、课堂教学、教改课改、教育管理、教师教育、教学案例、学科进展、学术论坛。 《求知导刊》征稿对象&#xff1a; 全国科技工作者、教育工作者&#xff0c;各级科技与教育部门的领导者以及管理…

面试笔记——工厂模式(简单工厂、工厂方法模式、抽象工厂模式)

场景需求&#xff1a;设计一个咖啡店点餐系统。 设计一个咖啡类&#xff08;Coffee&#xff09;&#xff0c;并定义其两个子类&#xff08;美式咖啡【AmericanCoffee】和拿铁咖啡【LatteCoffee】&#xff09;&#xff1b;再设计一个咖啡店类&#xff08;CoffeeStore&#xff09…

深度学习之基于YOLOv5草莓成熟度目标检测系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景与意义 草莓作为一种广受欢迎的水果&#xff0c;其成熟度的判断对于保证草莓的品质和口感至关重要。然…

python直接发布到网站wordpress之三批量发布图片

在前面的文章中&#xff0c;实现了使用python操作wordpress发布文字内容和图片内容。 python直接发布到网站wordpress之一只发布文字-CSDN博客 python直接发布到网站wordpress之二发布图片-CSDN博客 不过&#xff0c;此时发布图片的数量只能是一张图片。但在实际应用中&…

VINS预积分与误差模型

文章目录 IMU的测量值误差模型IMU预积分真实模型IMU预积分估计模型误差模型普通增量积分中值积分法 参考文献 IMU的测量值误差模型 IMU的测量值误差模型&#xff1a; a ^ t a t R w t g w b a t n a t ω ^ t ω t b ω t n ω t \begin{array}{} {{{\hat a}_t} {a_t…

10页面结构分析

我们打开一个网页&#xff0c;都会有一个清晰的结构和布局上图中的标签就是用来划分各个部分区域用的。其中比较常用重要的是header、footer和nav&#xff0c;需要重点掌握。 下面是部分代码及效果演示 <header> <h2>网页头部</h2> </header><sec…

C++实现二叉搜索树(模型)

目录 1.二叉搜索树的概念 2.二叉搜索树的实现 2.1总体代码预览 2.2各个函数实现原理 链表结构体 二叉搜索树的成员变量 二叉搜索树的插入 二叉搜索树的查找 二叉搜索树的遍历 二叉搜索树的删除 1.二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#…

AI去衣技术在动画制作中的应用

随着科技的发展&#xff0c;人工智能&#xff08;AI&#xff09;已经在各个领域中发挥了重要作用&#xff0c;其中包括动画制作。在动画制作中&#xff0c;AI去衣技术是一个重要的工具&#xff0c;它可以帮助动画师们更加高效地完成工作。 AI去衣技术是一种基于人工智能的图像…

jenkins目录下的vue3项目——pnpm install后运行报错——奇葩问题解决

昨天到今天&#xff0c;同事那边遇到一个问题&#xff0c;就是关于vue3vite的项目&#xff0c;在执行了自动打包后&#xff0c;运行代码会提示报错的问题。 报错信息如下&#xff1a; 具体错误信息如下&#xff1a; ERROR 11:28:14 [vite] Pre-transform error: Cannot find …

C语言实战项目---通讯录

项目要实现的内容&#xff1a;能够存放100个人的通讯录程序&#xff0c;能够实现联系人数据的存储&#xff0c;删除&#xff0c;修改&#xff0c;查找&#xff0c;展示联系人的信息。 所需知识&#xff1a;结构体&#xff0c;指针&#xff0c;函数................. 废话不多…

AI绘画成果展(第一期)

免费获取更多原图&#xff0c;备注“AI绘画”&#xff0c;可在文章末尾点击名片进qun获取。 免费获取更多原图&#xff0c;备注“AI绘画”&#xff0c;可在文章末尾点击名片进qun获取。

pandas索引

pandas索引 一、索引1.1 建立索引1.2 重置索引1.3 索引类型1.4 索引的属性1.5 索引的操作 一、索引 1.1 建立索引 建立索引可以在数据读取加载中指定索引&#xff1a; import pandas as pd df pd.read_excel(team.xlsx, index_colname) # 将name列设置为索引 df.head()效…