本系列参考黑马程序员微服务课程,有兴趣的可以去查看相关视频,本系列内容采用渐进式方式讲解微服务核心概念与实践方法,每日更新确保知识点的连贯性。通过系统化学习路径帮助开发者掌握分布式系统构建的关键技术。读者可通过平台订阅功能获取最新章节推送,及时了解服务拆分、容器化部署、服务网格等前沿技术动态。
- 个人主页:VON
- 文章所属专栏:微服务
- 系列文章链接:暂无
- 时间:每天12点准时更新
目录
前言
一、MyBatis-Plus 与 MyBatis 的区别
功能增强
开发效率
扩展性
适用场景
示例对比
二、引入Mybits-Plus
1.下载依赖
2.继承BaseMapper编辑
3、修改代码
4.测试
插入
查询 (单条数据)
查询 (多条数据)
更新数据
编辑 删除数据
三、常见注解
@TableName
示例:
@TableId
示例:
@TableField
常见的配置
四、条件构造器
1、基于QueryWrapper查询
2、基于UpdateWrapper更新
五、自定义SQL
六、Service接口
1、基础用法
2、实现简单业务接口
3、实现复杂业务接口
4.开始测试
(1)增加用户信息
(2)查询用户信息
(3)批量查询用户信息
(4)扣减用户余额
(5)删除用户信息
(6)根据Lambda查询用户信息
编辑
(7)IService批量新增
结语
前言
蝉鸣撕心裂肺时,VON从冷汗里弹起来。
泛黄的墙壁,潦草的名字,2030 年 7 月 15 日的日历 —— 这不是他被总监骂 "连 MybatisPlus 都不会" 的会议室。
他重生回了高考后的暑假。
前世因荒废假期,他在大学跟不上课程,工作后写几百行冗余 SQL 被嘲笑,看同事玩转微服务自己却连基础都摸不透。那些羞辱像针一样扎着。
班长的消息弹出来:"学长推荐了入门微服务的资料,从 MybatisPlus 开始。"
VON盯着那行字,心脏狂跳。前世他就是嫌难,把整个夏天耗在了游戏里。
"这次不能再错过。"
他抓起手机,点开前世屏蔽的技术公众号,目光落在《MybatisPlus 基础入门》上。窗外的蝉鸣突然温顺了,阳光在崭新的教程封面上,映出他眼里的光。
重生第一天,就从搞懂 MybatisPlus 开始。
一、MyBatis-Plus 与 MyBatis 的区别
Mybits-Plus官网
Mybits官网
MyBatis-Plus(简称 MP)是基于 MyBatis 的增强工具,旨在简化开发并提高效率,核心区别如下:
功能增强
MyBatis-Plus 在 MyBatis 基础上提供了大量开箱即用的功能:
- 自动化 CRUD:内置通用 Mapper 和 Service,无需手动编写基础 SQL。
- 条件构造器:通过
QueryWrapper
、UpdateWrapper
等实现动态 SQL 拼接。 - 代码生成器:自动生成实体类、Mapper、Service 等代码。
- 分页插件:内置分页支持,无需额外配置。
开发效率
MyBatis 需要手动编写 SQL 和结果映射,而 MyBatis-Plus 通过约定优于配置减少冗余代码:
- 默认映射实体类与数据库表字段(支持驼峰转换)。
- 提供 Lambda 表达式写法,避免硬编码字段名。
扩展性
- MyBatis-Plus 完全兼容原生 MyBatis,可混合使用。
- 支持自定义全局操作(如逻辑删除、自动填充字段)。
适用场景
- MyBatis:需高度定制复杂 SQL 或已有成熟 MyBatis 项目。
- MyBatis-Plus:快速开发常规业务(如后台管理系统),减少样板代码。
示例对比
MyBatis 示例:
MyBatis-Plus 等价操作:
二、引入Mybits-Plus
1.下载依赖
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version>
</dependency>
2.继承BaseMapper
3、修改代码
原来代码👇
将原来代码中的语句直接删除
Mapper也同理
修改测试类中的方法即可,根据提示直接回车即可
4.测试
插入
插入成功
查询 (单条数据)
查询 (多条数据)
更新数据
删除数据
由此可见增删改查功能全部正常,目前的代码极大的简化了原本的代码
三、常见注解
@TableName
用于指定实体类对应的数据库表名。当实体类名与数据库表名不一致时,使用该注解进行映射。
@TableName("user_info")
public class User {// 类字段
}
示例:
@TableId
用于标识主键字段,并可以指定主键生成策略。常见的属性包括value
(数据库主键字段名)和type
(主键生成策略)。
@TableId(value = "id", type = IdType.AUTO)
private Long id;
主键生成策略(IdType
)常见选项:
AUTO
:数据库自增INPUT
:手动输入ASSIGN_ID
:雪花算法生成IDASSIGN_UUID
:生成UUID
示例:
这里测试一下自增
@TableField
用于标注非主键字段,解决字段名与数据库列名不一致的问题,或标识非表字段(如 transient 字段)。
@TableField("user_name")
private String name;@TableField(exist = false)
private String tempData;
常见属性:
value
:数据库字段名(默认与属性名一致时可不填)exist
:是否为数据库字段(默认为true
)fill
:字段自动填充策略(如FieldFill.INSERT
插入时填充)
注:当exist设置为false时该字段不显示
注:在数据库设计或查询中,偶尔会遇到表名与数据库保留关键字相同的情况。这可能导致语法错误或执行失败。以下是几种常见的解决方法:
使用引号或方括号包裹表名 不同数据库系统对保留关键字的处理方式不同。MySQL使用反引号(`),SQL Server使用方括号([]),PostgreSQL和Oracle使用双引号("")。例如:
-- MySQL
SELECT * FROM `order`;-- SQL Server
SELECT * FROM [order];-- PostgreSQL/Oracle
SELECT * FROM "order";
修改表名 避免使用数据库保留关键字作为表名是最佳实践。可以通过添加前缀或后缀来修改表名,例如tbl_order
或orders
。
使用别名 在查询中为表指定别名可以避免直接使用关键字。例如:
SELECT o.* FROM `order` AS o WHERE o.id = 1;
数据库保留关键字列表 不同数据库系统的保留关键字各不相同。
常见的配置
mybitis-plus:# 配置Mapper XML文件的位置mapper-locations: classpath*:mapper/*.xmlconfiguration:# 开启下划线转驼峰命名映射map-underscore-to-camel-case: true# 指定MyBatis日志实现方式,输出到控制台log-impl: org.apache.ibatis.logging.stdout.StdOutImpl# 关闭二级缓存cache-enabled: falseglobal-config:db-config:# 主键生成策略:自动递增id-type: auto# 逻辑删除字段名logic-delete-field: is_deleted# 逻辑删除值(标记为已删除)logic-delete-value: 1# 逻辑未删除值(标记为未删除)logic-not-delete-value: 0# 逻辑删除列名logic-delete-column: is_deleted# 逻辑删除类型为列模式logic-delete-type: COLUMN# 数据库类型db-type: mysql# 表前缀table-prefix: tbl_# 字段策略:智能判断非空字段field-strategy: smart# 更新策略:智能判断非空字段update-strategy: smart# 插入策略:智能判断非空字段insert-strategy: smart
一般配置成这样就可以了
想要了解更多的可以看官方文档👇
文章开头部分已经引入了文档官网
四、条件构造器
1、基于QueryWrapper查询
//条件构造器测试案例@Testvoid textOne1(){//查询名字带o,并且存款大于1000的用户List<User> users = userMapper.selectList(new QueryWrapper<User>().like("username", "o").gt("balance", 1000));users.forEach(System.out::println);}@Testvoid textOne2(){//将张三存款改为10000User user = new User();user.setBalance(10000);QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username", "张a三");userMapper.update(user, wrapper);}
可见查询到了一条符合的语句
可见余额已经修改为10000了
2、基于UpdateWrapper更新
@Testvoid textTwo1(){//基于UpdateWrapper更新id为1,2,3的用户余额减500UpdateWrapper<User> wrapper = new UpdateWrapper<User>().in("id", 1, 2, 3).setSql("balance = balance - 500");userMapper.update(null, wrapper);}
更新前的数据如下
更新后的数据
五、自定义SQL
这种写法是 “用分层设计让代码更干净,用动态条件适配变化,用 XML 管好 SQL ,用测试保障质量” ,本质是为了让数据库操作的 “开发更灵活、维护更简单、协作更顺畅、质量更可控”
测试用例驱动(功能触发层)
编写 textCustomSqlQuery
测试方法,先定义更新参数(用户 ID 列表 ids
、扣除金额 amount
),再用 QueryWrapper
构建 id IN (1,2,3)
的条件,最后调用 userMapper.updateBalanceByIds
,作为功能入口触发数据库操作。
Mapper 接口约定(方法声明层)
在 UserMapper
接口中定义 updateBalanceByIds
方法,通过 @Param
明确入参(条件 wrapper
、金额 amount
),约定参数传递规则,作为 XML 映射 SQL 的 “调用声明”。
XML 映射执行(SQL 实现层)
XML 中通过 <update id="updateBalanceByIds">
绑定接口方法,编写 SQL :UPDATE tb_user SET balance = balance - #{amount} ${ew.customSqlSegment}
,既用 #{amount}
安全传参,又通过 ${ew.customSqlSegment}
拼接条件,最终在数据库执行 “按 ID 批量扣余额” 的更新。
测试用例负责场景触发,Mapper 接口定义调用契约,XML 映射实现具体 SQL ,协同完成数据库更新逻辑。
六、Service接口
1、基础用法
只需继承一下接口即可
这里做一个简单的测试
直接就可以对数据库中的数据进行修改
2、实现简单业务接口
添加配置文件
<!--swagger--><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi2-spring-boot-starter</artifactId><version>4.1.0</version></dependency><!--web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
修改yaml文件,加入以下代码
knife4j:enable: trueopenapi:group:default:group-name: defaultapi-rule: packageapi-rule-resources:- com.itheima.mp.controller
添加UserVO和UserFormDTO两个实体类
开始写Controller代码
package com.itheima.mp.controller;import cn.hutool.core.bean.BeanUtil;
import com.itheima.mp.domain.dto.UserFormDTO;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.vo.UserVO;
import com.itheima.mp.service.IUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;import java.util.List;@Api(tags = "用户管理相关接口")
@RequestMapping("/users")
@RestController
@RequiredArgsConstructor
public class UserController {private final IUserService userService;@ApiOperation("新增用户")@PostMappingpublic void saveUser(@RequestBody UserFormDTO userDTO){//1.把DTO转换成POUser user = BeanUtil.copyProperties(userDTO,User.class);//2.调用service完成新增userService.save(user);}@ApiOperation("删除用户")@DeleteMapping("/{id}")public void deleteUserById(@ApiParam("用户id") @PathVariable("id") Long id){userService.removeById(id);}@ApiOperation("查询用户")@GetMapping("/{id}")public UserVO queryUserById(@ApiParam("用户id") @PathVariable("id") Long id){//1.查询用户POUser user = userService.getById(id);//2.把PO转换成VOreturn BeanUtil.copyProperties(user,UserVO.class);}@ApiOperation("批量查询用户")@GetMapping("/{id}")public List<UserVO> queryUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids){//1.查询用户POList<User> users = userService.listByIds(ids);//2.把PO转换成VOreturn BeanUtil.copyToList(users,UserVO.class);}
}
3、实现复杂业务接口
这里的请求方式是PUT请求,这里写错了,留意一下
最后一行的id应该是id的,这里写成ew了🤡🤡🤡
4.开始测试
这里用的是Apifox
(1)增加用户信息
发送post请求
成功插入数据
(2)查询用户信息
注意下这里是GET请求
(3)批量查询用户信息
(4)扣减用户余额
这里是PUT请求
这里扣减id为5的用户
余额变成9000了
(5)删除用户信息
删除id为7的用户
可以看到id为7的用户被删除了
以上的测试后端也都响应回来了
(6)根据Lambda查询用户信息
先创建一个实体类,参数多的情况下不建议一个一个输入
controller和service层代码
注意下这里的请求路径为了和上文区分改成了list
看下实体类中的参数,都可以进行查询
这里的状态码全为1,所以没有查询到状态码为2的。
细心的话不难发现2号余额为负数
先将他的余额设置成100,然后在减余额
这里的逻辑改了一下,用户余额为0时会改变状态,也就是冻结用户
调整好代码后接着测试扣减余额
注意下这里的请求方式和参数
可以看到状态和余额都改变了
(7)IService批量新增
注:这里需要打开mysql的一个参数
将这个字段设置为true即可。
结语
这篇关于 MyBatis - Plus 学习的文章,其诞生如同一场与代码世界的深度邂逅。从暮色浸染的傍晚 6 点,到星光缀满夜空的凌晨 0:37,除去 30 分钟短暂的用餐时光,近 6 小时的全神贯注,最终打磨出这篇约 7000 字的学习记录。
每一个字符都凝结着对 MyBatis - Plus 知识点的反复推敲,每一步操作过程的呈现都力求精准还原技术实践,每一处运行结果的记录都饱含对细节的极致追求 —— 这份从指尖流淌而出的文字,不仅是时间的沉淀,更是对 MyBatis - Plus 实操细节的细致捕捉。
唯愿这份带着钻研热忱与满满诚意的记录,能为正在学习 MyBatis - Plus 的你扫清障碍,提供切实的参考与助益,让你的学习之路更顺畅。
最后附上文章全套代码
代码参考黑马程序员资料
UserController
package com.itheima.mp.controller;import cn.hutool.core.bean.BeanUtil;
import com.itheima.mp.domain.dto.UserFormDTO;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.query.UserQuery;
import com.itheima.mp.domain.vo.UserVO;
import com.itheima.mp.service.IUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;import java.util.List;@Api(tags = "用户管理相关接口")
@RequestMapping("/users")
@RestController
@RequiredArgsConstructor
public class UserController {private final IUserService userService;@ApiOperation("新增用户")@PostMappingpublic void saveUser(@RequestBody UserFormDTO userDTO){//1.把DTO转换成POUser user = BeanUtil.copyProperties(userDTO,User.class);//2.调用service完成新增userService.save(user);}@ApiOperation("删除用户")@DeleteMapping("/{id}")public void deleteUserById(@ApiParam("用户id") @PathVariable("id") Long id){userService.removeById(id);}@ApiOperation("查询用户")@GetMapping("/{id}")public UserVO queryUserById(@ApiParam("用户id") @PathVariable("id") Long id){//1.查询用户POUser user = userService.getById(id);//2.把PO转换成VOreturn BeanUtil.copyProperties(user,UserVO.class);}@ApiOperation("批量查询用户")@GetMappingpublic List<UserVO> queryUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids){//1.查询用户POList<User> users = userService.listByIds(ids);//2.把PO转换成VOreturn BeanUtil.copyToList(users,UserVO.class);}@ApiOperation("扣减余额")@PutMapping("/{id}/deduction/{money}")public void deductBalance(@ApiParam("用户id") @PathVariable("id") Long id,@ApiParam("金额") @PathVariable("money") Integer money){userService.deductBalance(id,money);}@ApiOperation("根据复杂条件查询用户")@GetMapping("/list")public List<UserVO> queryUserByIds(UserQuery query){//1.查询用户POList<User> users = userService.queryUsers(query.getName(),query.getStatus(),query.getMinBalance(),query.getMaxBalance());//2.把PO转换成VOreturn BeanUtil.copyToList(users,UserVO.class);}
}
User
package com.itheima.mp.domain.po;import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.time.LocalDateTime;
@TableName("tb_user")
@Data
public class User {/*** 用户id*/private Long id;/*** 用户名*/private String username;/*** 密码*/private String password;/*** 注册手机号*/private String phone;/*** 详细信息*/private String info;/*** 使用状态(1正常 2冻结)*/private Integer status;/*** 账户余额*/private Integer balance;/*** 创建时间*/private LocalDateTime createTime;/*** 更新时间*/private LocalDateTime updateTime;
}
UserQuery
package com.itheima.mp.domain.query;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;@Data
@ApiModel(description = "用户查询条件实体")
public class UserQuery {@ApiModelProperty("用户名关键字")private String name;@ApiModelProperty("用户状态:1-正常,2-冻结")private Integer status;@ApiModelProperty("余额最小值")private Integer minBalance;@ApiModelProperty("余额最大值")private Integer maxBalance;
}
UserVO
package com.itheima.mp.domain.vo;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;@Data
@ApiModel(description = "用户VO实体")
public class UserVO {@ApiModelProperty("用户id")private Long id;@ApiModelProperty("用户名")private String username;@ApiModelProperty("详细信息")private String info;@ApiModelProperty("使用状态(1正常 2冻结)")private Integer status;@ApiModelProperty("账户余额")private Integer balance;
}
UserMapper
package com.itheima.mp.mapper;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.mp.domain.po.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
import org.springframework.core.Constants;import java.util.List;public interface UserMapper extends BaseMapper<User> {
// List<User> queryUserByIds(@Param("ids") List<Long> ids);void updateBalanceByIds(@Param("ew") QueryWrapper<User> wrapper, @Param("amount") int amount);@Update("update tb_user set balance = balance - #{money} where id = #{id}")void deductBalance(@Param("id") Long id, @Param("money") Integer money);
}
UserServiceImpl
package com.itheima.mp.service.impl;import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.mapper.UserMapper;
import com.itheima.mp.service.IUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Override@Transactionalpublic void deductBalance(Long id, Integer money) {//1.查询用户User user = getById(id);//2.更新用户余额if(user == null || user.getStatus() == 2){throw new RuntimeException("用户不存在");}if(user.getBalance() < money){throw new RuntimeException("余额不足");}//余额为0时冻结用户int remainBalance = user.getBalance() - money;lambdaUpdate().set(User::getBalance, remainBalance).set(remainBalance == 0, User::getStatus, 2).eq(User::getBalance,user.getBalance()).eq(User::getId, id).update();}@Overridepublic List<User> queryUsers(String name, Integer status, Integer minBalance, Integer maxBalance) {return lambdaQuery().like(name!=null, User::getUsername, name).eq(status!=null, User::getStatus, status).ge(minBalance!=null, User::getBalance, minBalance).le(maxBalance!=null, User::getBalance, maxBalance).list();}
}
IUserService
package com.itheima.mp.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.mp.domain.po.User;import java.util.List;public interface IUserService extends IService<User> {void deductBalance(Long id, Integer money);List<User> queryUsers(String name, Integer status, Integer minBalance, Integer maxBalance);
}
yaml
spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=truetype: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: 123456
logging:level:com.itheima: debugpattern:dateformat: HH:mm:ss
#mybatis:
# mapper-locations: classpath*:mapper/*.xml
mybitis-plus:mapper-locations: classpath*:mapper/*.xmlconfiguration:map-underscore-to-camel-case: truecache-enabled: falseglobal-config:db-config:id-type: autoupdate-strategy: not_null
knife4j:enable: trueopenapi:group:default:group-name: defaultapi-rule: packageapi-rule-resources:- com.itheima.mp.controller
UserMapperTest
package com.itheima.mp.mapper;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.itheima.mp.domain.po.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.time.LocalDateTime;
import java.util.List;@SpringBootTest
class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testvoid testInsert() {User user = new User();//user.setId(5L);user.setUsername("张a三");user.setPassword("123");user.setPhone("18688990012");user.setBalance(200);user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");user.setCreateTime(LocalDateTime.now());user.setUpdateTime(LocalDateTime.now());userMapper.insert(user);}@Testvoid testSelectById() {User user = userMapper.selectById(5L);System.out.println("user = " + user);}@Testvoid testQueryByIds() {List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L));users.forEach(System.out::println);}@Testvoid testUpdateById() {User user = new User();user.setId(5L);user.setBalance(20000);userMapper.updateById(user);}@Testvoid testDeleteUser() {userMapper.deleteById(5L);}//条件构造器测试案例@Testvoid textOne1() {//查询名字带o,并且存款大于1000的用户List<User> users = userMapper.selectList(new QueryWrapper<User>().like("username", "o").gt("balance", 1000));users.forEach(System.out::println);}@Testvoid textOne2() {//将张三存款改为10000User user = new User();user.setBalance(10000);QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username", "张a三");userMapper.update(user, wrapper);}@Testvoid textTwo1() {//基于UpdateWrapper更新id为1,2,3的用户余额减500UpdateWrapper<User> wrapper = new UpdateWrapper<User>().in("id", 1, 2, 3).setSql("balance = balance - 500");userMapper.update(null, wrapper);}@Testvoid textCustomSqlQuery() {//1.更新条件List<Long> ids = List.of(1L, 2L, 3L);int amount = 100;//2.定义条件QueryWrapper<User> wrapper = new QueryWrapper<User>().in("id", ids);//3.调用 方法userMapper.updateBalanceByIds(wrapper, amount);}
}
IUserServiceTest
package com.itheima.mp.service;import com.itheima.mp.domain.po.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestExecutionListeners;import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class IUserServiceTest {@Autowiredprivate IUserService userService;@Testvoid testSaveUser(){User user = new User();//user.setId(5L);user.setUsername("张三aaa");user.setPassword("123");user.setPhone("18688990012");user.setBalance(200);user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");user.setCreateTime(LocalDateTime.now());user.setUpdateTime(LocalDateTime.now());userService.save(user);}@Testvoid testQuery(){List<User> list = userService.listByIds(List.of(1L, 2L, 3L));list.forEach(System.out::println);}@Testvoid testSaveBatch(){List<User> list = new ArrayList<>(10000);long b = System.currentTimeMillis();for (int i = 1; i <= 100000; i++) {User user = new User();user.setUsername("user" + i);user.setPassword("<PASSWORD>");user.setPhone("12345678901");user.setStatus(1);user.setBalance(100);user.setCreateTime(LocalDateTime.now());user.setUpdateTime(LocalDateTime.now());list.add(user);if(i%10000==0){userService.saveBatch(list);list.clear();}}long e = System.currentTimeMillis();System.out.println("耗时:"+(e-b));}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.12</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.itheima.mp</groupId><artifactId>mp-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>mp-demo</name><description>Demo project for Spring Boot</description><properties><java.version>11</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
<!-- <dependency>-->
<!-- <groupId>org.mybatis.spring.boot</groupId>-->
<!-- <artifactId>mybatis-spring-boot-starter</artifactId>-->
<!-- <version>2.3.1</version>-->
<!-- </dependency>-->
<!-- mybits plus依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version></dependency><!--swagger--><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi2-spring-boot-starter</artifactId><version>4.1.0</version></dependency><!--web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.11</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>