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://www.mzph.cn/pingmian/10911.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机服务器中了360后缀勒索病毒怎么解密,360后缀勒索病毒恢复

计算机网络技术的不断发展与应用&#xff0c;为企业的生产运营提供了极大便利&#xff0c;大大提高了企业的办公效率&#xff0c;为企业的生产运营注入了新的动力&#xff0c;但网络是一把双刃剑&#xff0c;在为企业提供便利的同时&#xff0c;也为企业的数据安全带来严重威胁…

google test 使用指南

目录 测试项目 calculator.h calculator.cpp test01.cpp 创建新项目 选择Google Test 选择要测试的项目 pch.cpp 加入依赖 设为启动项目 ​编辑 运行 ​编辑 关键点 测试项目 calculator.h #ifndef __CALCULATOR_H__ #define __CALCULATOR_H__#include <i…

Linux操作系统中管理磁盘的另外一种操作方式。即LVM——逻辑卷管理操作

在Linux操作系统中管理磁盘的一种方法名称——LVM&#xff0c;这种管理磁盘的优势。 1.使用LVM去管理磁盘可以在不影响原来数据的前提下去扩容磁盘空间或者是缩减磁盘空间。 在LVM中除了上层逻辑券可以扩容&#xff0c;下层的券组也可以扩容。 2.使用LVM管理的磁盘支持快照功…

MySQL中的子查询

子查询,在一个查询语句中又出现了查询语句 子查询可以出现在from和where后面 from 表子查询(结果一般为多行多列)把查询结果继续当一张表对待 where 标量子查询(结果集只有一行一列)查询身高最高的学生,查询到一个最高身高 列子查询(结果集只有一行多列) 对上表进行如下操作 …

韩顺平0基础学Java——第10天

p202-233 类与对象&#xff08;第七章&#xff09; 成员方法 person类中的speak方法&#xff1a; 1.public表示方法是公开的 2.void表示方法没有返回值 3.speak&#xff08;&#xff09;中&#xff0c;speak表示方法名&#xff0c;括号是形参列表。 4.大括号为方法体&am…

WPF之多种视图切换

1&#xff0c;View切换&#xff0c;效果呈现 视图1 视图2 视图3 2&#xff0c;在Xaml中添加Listview控件&#xff0c;Combobox控件。 <Grid ><Grid.RowDefinitions><RowDefinition Height"143*"/><RowDefinition Height"30"/>&l…

Leetcode经典题目之用队列实现栈

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 目录 1、题目展示2、题目分析3、完整代码演示4、结语 1、题目展示 前面我们了解过如何实现队列…

第五百回 Get路由管理

文章目录 1. 概念介绍2. 使用方法2.1 普通路由2.2 命名路由 3. 示例代码4. 内容总结 我们在上一章回中介绍了"使用get显示Dialog"相关的内容&#xff0c;本章回中将介绍使用get进行路由管理.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章…

掌握MySQL常用的命令

前言 MySQL是一个流行的开源关系型数据库管理系统&#xff0c;广泛应用于各种应用场景。熟练掌握MySQL的常用命令&#xff0c;对于数据库管理员和开发人员来说至关重要。本文将介绍MySQL数据库的一些基础术语、SQL语言分类&#xff0c;以及DDL、DML、DQL和DCL等操作&#xff0…

C++类与对象的一些练习

1.设计一个名为Rectangle的矩形类&#xff0c;其属性为矩形的长和宽&#xff0c;能计算和输出矩形的周长和面积。 class Rectangle { public:Rectangle(int c0,int k0):m_c(c),m_k(k){}int length()//周长{return 2 * (m_c m_k);}int area()//面积{return m_c * m_k;} privat…

如何优雅简单地写 Controller 层代码?

本篇就来介绍一下&#xff0c;如何写好一个 controller &#xff0c;让你的接口变的更加优雅&#xff01; 一个完整的后端请求由 4 部分组成&#xff1a; 接口地址&#xff08;也就是 URL 地址&#xff09; 请求方式&#xff08;一般就是 get、set&#xff0c;当然还有 put、…

算法-排序详解

目录 前言 比较排序 选择排序 插入排序 冒泡排序 归并排序 快速排序 非比较类排序 计数排序 桶排序 基数排序 排序的稳定性 排序算法的题目 前言 计算机的工作之一就是对数据的处理&#xff0c;处理数据有一个常见的操作就是对数据排序&#xff0c;比如新闻系统总…

Linux——进程间通信

目录 一、进程通信的初步认识 1.1 进程间通信目的 1.2 进程间通信的种类 管道&#xff08;Pipes&#xff09; System V IPC POSIX IPC 三、管道 3.1 知识铺垫 3.2 匿名管道 3.2.1 基本概念 3.2.2 测试用例&#xff1a; 3.3 管道的行为 3.4 命名管道 3.4.1 基本概念…

Django Admin后台管理:高效开发与实践

title: Django Admin后台管理&#xff1a;高效开发与实践 date: 2024/5/8 14:24:15 updated: 2024/5/8 14:24:15 categories: 后端开发 tags: DjangoAdmin模型管理用户认证数据优化自定义扩展实战案例性能安全 第1章&#xff1a;Django Admin基础 1.1 Django Admin简介 Dj…

手撕C语言题典——反转链表

目录 前言 一.思路 1&#xff09;创建新链表 2&#xff09;创建三个指针 二.代码实现 搭配食用更佳哦~~ 数据结构之单单单——链表-CSDN博客 数据结构之单链表的基本操作-CSDN博客 前面学了单链表的相关知识&#xff0c;我们来尝试做一下关于顺序表的经典算法题~ 前言 反转…

Github 2024-05-12 php开源项目日报 Top10

根据Github Trendings的统计,今日(2024-05-12统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量PHP项目10Filament: 加速Laravel开发的完美起点 创建周期:1410 天开发语言:PHP协议类型:MIT LicenseStar数量:12228 个Fork数量:1990 次关…

Isaac Sim 4 键盘控制小车前进方向(学习笔记5.8.2)

写的乱糟糟&#xff0c;主要是这两周忘了记录了...吭哧吭哧往下搞&#xff0c;突然想起来要留档&#xff0c;先大致写一个&#xff0c;后面再往里添加和修改吧&#xff0c;再不写就全忘了 有一个一直没解决的问题&#xff1a; 在保存文件时出现问题&#xff1a;isaac sim mism…

Docker学习(带图详细)

一、安装docker 参考官方文档&#xff1a;https://docs.docker.com/engine/install/centos/ 查看系统版本 [rootlocalhost ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core) [rootlocalhost ~]# [rootlocalhost ~]# uname -a Linux localhost.localdomai…

vs code中如何使用git

由于本地代码有了一些储备&#xff0c;所以想通过网址托管形式&#xff0c;之前一直使用了github&#xff0c;但是鉴于一直被墙&#xff0c;无法登录账号&#xff0c;所以选择了国内的gitee来作为托管网站。 gitee的网址&#xff1a;Gitee - 基于 Git 的代码托管和研发协作平台…

在另外一个页面,让另外一个页面弹框显示操作(调佣公共的弹框)

大概意思是&#xff0c;登录弹框在另外一个页面中&#xff0c;而当前页面不存在&#xff0c;在当前页面中判断如果token不存在&#xff0c;就弹框出登录的弹框 最后一行 window.location.href … 如果当前用户已登录&#xff0c;则执行后续操作(注意此处&#xff0c;可不要)