MyBatis Plus 批量數據插入功能,yyds!
作者 | 王磊
來源 | Java中文社群(ID:javacn666)
轉載請聯系授權(微信ID:GG_Stone
最近 Review 小伙伴代碼的時候,發現了一個小小的問題,小伙伴竟然在 for 循環中進行了 insert (插入)數據庫的操作,這就會導致每次循環時都會進行連接、插入、斷開連接的操作,從而導致一定的性能問題,簡化后代碼如下:
- /**
- * 插入操作
- */
- @RequestMapping("/save")
- public Object save() {
- boolean flag = false; // 返回結果
- // 待添加(用戶)數據
- for (int i = 0; i < 1000; i++) {
- User user = new User();
- user.setName("test:"+i);
- user.setPassword("123456");
- // 插入數據
- flag = userService.save(user);
- if(!flag) break;
- }
- return flag;
- }
這樣做并不會改變程序最終的執行結果,但會對程序的執行效率帶來很大的影響,就好比你現在要從 A 地點送 10 件貨到 B 地點,你可以選擇 1 次送 1 件,送 10 次的方案;也可以選擇 1 次送 10 件,送 1 次的方案,請問你會選擇哪種?這就是多次循環插入和批量一次插入的問題。
- PS:要插入的數據量越大,批量插入的時間(相比于循環多次插入來說)也越短、其優勢也越大。
批量插入實現方案
本文我們使用 MyBatis-Plus(下文簡稱 MP)自帶的 saveBatch 方法,來實現數據的批量插入功能,因為 MP 不是本文討論的重點,所以這里咱們就不介紹了,如果有不熟悉的朋友可以去他的官方自行惡補:https://baomidou.com/guide/,咱們本文重點介紹一下 MP 實現批量插入的具體步驟。
1.引入 MP 框架
首先,打開您的 pom.xml 文件,在文件中添加以下內容:
- <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.創建數據庫和表
此步驟可省略,主要用于本文功能的實現,創建數據庫和數據表的腳本如下:
- -- ----------------------------
- -- 創建數據庫
- -- ----------------------------
- SETNAMES utf8mb4;
- SET FOREIGN_KEY_CHECKS = 0;
- DROPDATABASEIFEXISTS`testdb`;
- CREATEDATABASE`testdb`;
- USE`testdb`;
- -- ----------------------------
- -- 創建 user 表
- -- ----------------------------
- DROPTABLEIFEXISTS`user`;
- CREATETABLE`user` (
- `id`int(11) NOTNULL AUTO_INCREMENT,
- `name`varchar(255) CHARACTERSET utf8mb4 COLLATE utf8mb4_bin NULLDEFAULTNULL,
- `password`varchar(255) CHARACTERSET utf8mb4 COLLATE utf8mb4_bin NULLDEFAULTNULL,
- `createtime` datetime NULLDEFAULTCURRENT_TIMESTAMP,
- PRIMARY KEY (`id`) USING BTREE
- ) ENGINE = InnoDB AUTO_INCREMENT = 6CHARACTERSET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;
- -- ----------------------------
- -- 添加測試數據
- -- ----------------------------
- INSERTINTO`user`VALUES (1, '趙云', '123456', '2021-09-10 18:11:16');
- INSERTINTO`user`VALUES (2, '張飛', '123456', '2021-09-10 18:11:28');
- INSERTINTO`user`VALUES (3, '關羽', '123456', '2021-09-10 18:11:34');
- INSERTINTO`user`VALUES (4, '劉備', '123456', '2021-09-10 18:11:41');
- INSERTINTO`user`VALUES (5, '曹操', '123456', '2021-09-10 18:12:02');
- SET FOREIGN_KEY_CHECKS = 1;
3.具體代碼實現(重點)
① 實體類
先來創建數據庫所對應的 User 實體類:
- import lombok.Getter;
- import lombok.Setter;
- import java.util.Date;
- @Getter
- @Setter
- publicclass User {
- privateint id;
- private String name;
- private String password;
- private Date createtime;
- }
② Controller 層代碼
本文的核心是使用 MP 框架中,IService 類提供的 saveBatch 方法,來實現批量數據的插入功能,對應在 Controller 中的實現代碼如下:
- 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")
- publicclass UserController {
- @Autowired
- private UserServiceImpl userService;
- /**
- * MP 批量插入
- */
- @RequestMapping("/savebatch")
- public boolean saveBatch() {
- List<User> list = new ArrayList<>();
- // 待添加(用戶)數據
- 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 層代碼(重點)
接下來,我們要創建一個 UserService 接口,繼承 MP 框架中的 IService 接口,實現代碼如下:
- import com.baomidou.mybatisplus.extension.service.IService;
- import com.example.demo.model.User;
- publicinterface UserService extends IService<User> {
- }
然后再創建一個 UserService 的實現類:
- 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
- publicclass UserServiceImpl extends ServiceImpl<UserMapper,User>
- implements UserService {
- }
- PS:注意 UserServiceImpl 必須要繼承 MP 框架中的 ServiceImpl,不然要重寫很多方法。
④ Mapper 層代碼
Mapper 層的實現相對來說就比較簡單了,只需要創建一個 Mapper 類繼承 MP 框架中的 BaseMapper 類即可,實現代碼如下:
- import com.baomidou.mybatisplus.core.mapper.BaseMapper;
- import com.example.demo.model.User;
- import org.apache.ibatis.annotations.Mapper;
- @Mapper
- publicinterface UserMapper extends BaseMapper<User>{
- }
- PS:BaseMapper 提供了對某個對象(類)最基礎的 CRUD 操作。
總結
本文我們介紹了 MP(MyBatis Plus)中實現批量插入的具體實現步驟,它的核心是通過調用 MP 中 IService 提供的 saveBatch 方法來完成的,但如果項目中沒有引入 MP 框架該如何處理?是不是使用了 MP 就可以躺平了呢?
不著急,下篇我們再聊批量插入的另一種方式(原生批量插入的實現方式),以及二者之間的優缺點分析。