一文了解MyBatis Plus批量數(shù)據(jù)插入功能
前言
最近 Review 小伙伴代碼的時候,發(fā)現(xiàn)了一個小小的問題,小伙伴竟然在 for 循環(huán)中進(jìn)行了 insert (插入)數(shù)據(jù)庫的操作,這就會導(dǎo)致每次循環(huán)時都會進(jìn)行連接、插入、斷開連接的操作,從而導(dǎo)致一定的性能問題,簡化后代碼如下:
/** * 插入操作 */ @RequestMapping("/save") public Object save() { boolean flag = false; // 返回結(jié)果 // 待添加(用戶)數(shù)據(jù) for (int i = 0; i < 1000; i++) { User user = new User(); user.setName("test:"+i); user.setPassword("123456"); // 插入數(shù)據(jù) flag = userService.save(user); if(!flag) break; } return flag; }
這樣做并不會改變程序最終的執(zhí)行結(jié)果,但會對程序的執(zhí)行效率帶來很大的影響,就好比你現(xiàn)在要從 A 地點送 10 件貨到 B 地點,你可以選擇 1 次送 1 件,送 10 次的方案;也可以選擇 1 次送 10 件,送 1 次的方案,請問你會選擇哪種?這就是多次循環(huán)插入和批量一次插入的問題。
PS:要插入的數(shù)據(jù)量越大,批量插入的時間(相比于循環(huán)多次插入來說)也越短、其優(yōu)勢也越大。
批量插入實現(xiàn)方案
本文我們使用 MyBatis-Plus(下文簡稱 MP)自帶的 saveBatch 方法,來實現(xiàn)數(shù)據(jù)的批量插入功能,因為 MP 不是本文討論的重點,所以這里咱們就不介紹了,如果有不熟悉的朋友可以去他的官方自行惡補(bǔ):https://baomidou.com/guide/,咱們本文重點介紹一下 MP 實現(xiàn)批量插入的具體步驟。
1.引入 MP 框架
首先,打開您的 pom.xml 文件,在文件中添加以下內(nèi)容:
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>mybatis-plus-latest-version</version> </dependency>
注意:mybatis-plus-latest-version 表示 MP 框架的最新版本號,可訪問 https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter 查詢最新版本號,但在使用的時候記得一定要將上面的 “mybatis-plus-latest-version”替換成換成具體的版本號,如 3.4.3 才能正常的引入框架。
2.創(chuàng)建數(shù)據(jù)庫和表
此步驟可省略,主要用于本文功能的實現(xiàn),創(chuàng)建數(shù)據(jù)庫和數(shù)據(jù)表的腳本如下:
-- ---------------------------- -- 創(chuàng)建數(shù)據(jù)庫 -- ---------------------------- SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; DROP DATABASE IF EXISTS `testdb`; CREATE DATABASE `testdb`; USE `testdb`; -- ---------------------------- -- 創(chuàng)建 user 表 -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL, `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL, `createtime` datetime NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic; -- ---------------------------- -- 添加測試數(shù)據(jù) -- ---------------------------- INSERT INTO `user` VALUES (1, '趙云', '123456', '2021-09-10 18:11:16'); INSERT INTO `user` VALUES (2, '張飛', '123456', '2021-09-10 18:11:28'); INSERT INTO `user` VALUES (3, '關(guān)羽', '123456', '2021-09-10 18:11:34'); INSERT INTO `user` VALUES (4, '劉備', '123456', '2021-09-10 18:11:41'); INSERT INTO `user` VALUES (5, '曹操', '123456', '2021-09-10 18:12:02'); SET FOREIGN_KEY_CHECKS = 1;
3.具體代碼實現(xiàn)(重點)
① 實體類
先來創(chuàng)建數(shù)據(jù)庫所對應(yīng)的 User 實體類:
import lombok.Getter; import lombok.Setter; import java.util.Date; @Getter @Setter public class User { private int id; private String name; private String password; private Date createtime; }
② Controller 層代碼
本文的核心是使用 MP 框架中,IService 類提供的 saveBatch 方法,來實現(xiàn)批量數(shù)據(jù)的插入功能,對應(yīng)在 Controller 中的實現(xiàn)代碼如下:
import com.example.demo.model.User; import com.example.demo.service.impl.UserServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.List; @RestController @RequestMapping("/u") public class UserController { @Autowired private UserServiceImpl userService; /** * MP 批量插入 */ @RequestMapping("/savebatch") public boolean saveBatch() { List<User> list = new ArrayList<>(); // 待添加(用戶)數(shù)據(jù) for (int i = 0; i < 1000; i++) { User user = new User(); user.setName("test:"+i); user.setPassword("123456"); list.add(user); } // 批量插入 return userService.saveBatch(list); } }
③ Service 層代碼(重點)
接下來,我們要創(chuàng)建一個 UserService 接口,繼承 MP 框架中的 IService 接口,實現(xiàn)代碼如下:
import com.baomidou.mybatisplus.extension.service.IService; import com.example.demo.model.User; public interface UserService extends IService<User> { }
然后再創(chuàng)建一個 UserService 的實現(xiàn)類:
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.example.demo.mapper.UserMapper; import com.example.demo.model.User; import com.example.demo.service.UserService; import org.springframework.stereotype.Service; @Service public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService { }
PS:注意 UserServiceImpl 必須要繼承 MP 框架中的 ServiceImpl,不然要重寫很多方法。
④ Mapper 層代碼
Mapper 層的實現(xiàn)相對來說就比較簡單了,只需要創(chuàng)建一個 Mapper 類繼承 MP 框架中的 BaseMapper 類即可,實現(xiàn)代碼如下:
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.demo.model.User; import org.apache.ibatis.annotations.Mapper; @Mapper public interface UserMapper extends BaseMapper<User>{ }
PS:BaseMapper 提供了對某個對象(類)最基礎(chǔ)的 CRUD 操作。
總結(jié)
本文我們介紹了 MP(MyBatis Plus)中實現(xiàn)批量插入的具體實現(xiàn)步驟,它的核心是通過調(diào)用 MP 中 IService 提供的 saveBatch 方法來完成的,但如果項目中沒有引入 MP 框架該如何處理?是不是使用了 MP 就可以躺平了呢?不著急,下篇我們再聊批量插入的另一種方式(原生批量插入的實現(xiàn)方式),以及二者之間的優(yōu)缺點分析。
相關(guān)文章
基于java file 文件操作operate file of java的應(yīng)用
本篇文章介紹了,基于java file 文件操作operate file of java的應(yīng)用。需要的朋友參考下2013-05-05SpringCloud服務(wù)的發(fā)現(xiàn)與調(diào)用詳解
在Java微服務(wù)越來越火的今天。幾乎什么公司都在搞微服務(wù)。而使用的比較多的就是Spring?Cloud技術(shù)棧。今天就來研究一下Spring?Cloud中服務(wù)發(fā)現(xiàn)與調(diào)用的基本原理2022-07-07SpringBoot如何切換成其它的嵌入式Servlet容器(Jetty和Undertow)
這篇文章主要介紹了SpringBoot如何切換成其它的嵌入式Servlet容器(Jetty和Undertow),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07詳解如何在Java項目中實現(xiàn)信號的連續(xù)接收
在Java項目中,信號的連續(xù)接收是一項重要的任務(wù),特別是在處理異步事件或者需要對外部事件做出響應(yīng)時,本篇博客將介紹如何在Java項目中實現(xiàn)信號的連續(xù)接收,包括信號的監(jiān)聽、處理和停止等步驟,需要的朋友可以參考下2023-11-11redis之基于SpringBoot實現(xiàn)Redis stream實時流事件處理方式
這篇文章主要介紹了redis之基于SpringBoot實現(xiàn)Redis stream實時流事件處理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06解決nacos項目啟動報錯:Connection refused: no further&
這篇文章主要介紹了解決nacos項目啟動報錯:Connection refused: no further informa問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04