

本系列参考黑马程序员微服务课程,有兴趣的可以去查看相关视频,本系列内容采用渐进式方式讲解微服务核心概念与实践方法,每日更新确保知识点的连贯性。通过系统化学习路径帮助开发者掌握分布式系统构建的关键技术。读者可通过平台订阅功能获取最新章节推送,及时了解服务拆分、容器化部署、服务网格等前沿技术动态。
蝉鸣撕心裂肺时,VON从冷汗里弹起来。
泛黄的墙壁,潦草的名字,2030 年 7 月 15 日的日历 —— 这不是他被总监骂 "连 MybatisPlus 都不会" 的会议室。
他重生回了高考后的暑假。
前世因荒废假期,他在大学跟不上课程,工作后写几百行冗余 SQL 被嘲笑,看同事玩转微服务自己却连基础都摸不透。那些羞辱像针一样扎着。
班长的消息弹出来:"学长推荐了入门微服务的资料,从 MybatisPlus 开始。"
VON盯着那行字,心脏狂跳。前世他就是嫌难,把整个夏天耗在了游戏里。
"这次不能再错过。"
他抓起手机,点开前世屏蔽的技术公众号,目光落在《MybatisPlus 基础入门》上。窗外的蝉鸣突然温顺了,阳光在崭新的教程封面上,映出他眼里的光。
重生第一天,就从搞懂 MybatisPlus 开始。
MyBatis-Plus(简称 MP)是基于 MyBatis 的增强工具,旨在简化开发并提高效率,核心区别如下:
MyBatis-Plus 在 MyBatis 基础上提供了大量开箱即用的功能:
QueryWrapper、UpdateWrapper 等实现动态 SQL 拼接。MyBatis 需要手动编写 SQL 和结果映射,而 MyBatis-Plus 通过约定优于配置减少冗余代码:
MyBatis 示例:
MyBatis-Plus 等价操作:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
原来代码👇

将原来代码中的语句直接删除

Mapper也同理

修改测试类中的方法即可,根据提示直接回车即可


插入成功




删除数据

由此可见增删改查功能全部正常,目前的代码极大的简化了原本的代码
用于指定实体类对应的数据库表名。当实体类名与数据库表名不一致时,使用该注解进行映射。
@TableName("user_info")
public class User {
// 类字段
}
用于标识主键字段,并可以指定主键生成策略。常见的属性包括value(数据库主键字段名)和type(主键生成策略)。
@TableId(value = "id", type = IdType.AUTO)
private Long id;主键生成策略(IdType)常见选项:
AUTO:数据库自增INPUT:手动输入ASSIGN_ID:雪花算法生成IDASSIGN_UUID:生成UUID这里测试一下自增

用于标注非主键字段,解决字段名与数据库列名不一致的问题,或标识非表字段(如 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/*.xml
configuration:
# 开启下划线转驼峰命名映射
map-underscore-to-camel-case: true
# 指定MyBatis日志实现方式,输出到控制台
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 关闭二级缓存
cache-enabled: false
global-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一般配置成这样就可以了

想要了解更多的可以看官方文档👇
文章开头部分已经引入了文档官网

//条件构造器测试案例
@Test
void textOne1(){
//查询名字带o,并且存款大于1000的用户
List<User> users = userMapper.selectList(new QueryWrapper<User>().like("username", "o").gt("balance", 1000));
users.forEach(System.out::println);
}
@Test
void textOne2(){
//将张三存款改为10000
User user = new User();
user.setBalance(10000);
QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username", "张a三");
userMapper.update(user, wrapper);
}可见查询到了一条符合的语句

可见余额已经修改为10000了

@Test
void textTwo1(){
//基于UpdateWrapper更新id为1,2,3的用户余额减500
UpdateWrapper<User> wrapper = new UpdateWrapper<User>().in("id", 1, 2, 3).setSql("balance = balance - 500");
userMapper.update(null, wrapper);
}更新前的数据如下

更新后的数据

这种写法是 “用分层设计让代码更干净,用动态条件适配变化,用 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}
测试用例负责场景触发,Mapper 接口定义调用契约,XML 映射实现具体 SQL ,协同完成数据库更新逻辑。
只需继承一下接口即可

这里做一个简单的测试

直接就可以对数据库中的数据进行修改


添加配置文件
<!--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: true
openapi:
group:
default:
group-name: default
api-rule: package
api-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("新增用户")
@PostMapping
public void saveUser(@RequestBody UserFormDTO userDTO){
//1.把DTO转换成PO
User 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.查询用户PO
User user = userService.getById(id);
//2.把PO转换成VO
return BeanUtil.copyProperties(user,UserVO.class);
}
@ApiOperation("批量查询用户")
@GetMapping("/{id}")
public List<UserVO> queryUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids){
//1.查询用户PO
List<User> users = userService.listByIds(ids);
//2.把PO转换成VO
return BeanUtil.copyToList(users,UserVO.class);
}
}这里的请求方式是PUT请求,这里写错了,留意一下
最后一行的id应该是id的,这里写成ew了🤡🤡🤡

这里用的是Apifox

发送post请求

成功插入数据
注意下这里是GET请求


这里是PUT请求

这里扣减id为5的用户

余额变成9000了

删除id为7的用户

可以看到id为7的用户被删除了

以上的测试后端也都响应回来了

先创建一个实体类,参数多的情况下不建议一个一个输入

controller和service层代码

注意下这里的请求路径为了和上文区分改成了list
看下实体类中的参数,都可以进行查询



这里的状态码全为1,所以没有查询到状态码为2的。

细心的话不难发现2号余额为负数

先将他的余额设置成100,然后在减余额
这里的逻辑改了一下,用户余额为0时会改变状态,也就是冻结用户

调整好代码后接着测试扣减余额
注意下这里的请求方式和参数

可以看到状态和余额都改变了


注:这里需要打开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("新增用户")
@PostMapping
public void saveUser(@RequestBody UserFormDTO userDTO){
//1.把DTO转换成PO
User 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.查询用户PO
User user = userService.getById(id);
//2.把PO转换成VO
return BeanUtil.copyProperties(user,UserVO.class);
}
@ApiOperation("批量查询用户")
@GetMapping
public List<UserVO> queryUserByIds(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids){
//1.查询用户PO
List<User> users = userService.listByIds(ids);
//2.把PO转换成VO
return 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.查询用户PO
List<User> users = userService.queryUsers(query.getName(),query.getStatus(),query.getMinBalance(),query.getMaxBalance());
//2.把PO转换成VO
return 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
@Transactional
public 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();
}
@Override
public 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=true
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
logging:
level:
com.itheima: debug
pattern:
dateformat: HH:mm:ss
#mybatis:
# mapper-locations: classpath*:mapper/*.xml
mybitis-plus:
mapper-locations: classpath*:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
global-config:
db-config:
id-type: auto
update-strategy: not_null
knife4j:
enable: true
openapi:
group:
default:
group-name: default
api-rule: package
api-rule-resources:
- com.itheima.mp.controllerUserMapperTest
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 {
@Autowired
private UserMapper userMapper;
@Test
void 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);
}
@Test
void testSelectById() {
User user = userMapper.selectById(5L);
System.out.println("user = " + user);
}
@Test
void testQueryByIds() {
List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L));
users.forEach(System.out::println);
}
@Test
void testUpdateById() {
User user = new User();
user.setId(5L);
user.setBalance(20000);
userMapper.updateById(user);
}
@Test
void testDeleteUser() {
userMapper.deleteById(5L);
}
//条件构造器测试案例
@Test
void textOne1() {
//查询名字带o,并且存款大于1000的用户
List<User> users = userMapper.selectList(new QueryWrapper<User>().like("username", "o").gt("balance", 1000));
users.forEach(System.out::println);
}
@Test
void textOne2() {
//将张三存款改为10000
User user = new User();
user.setBalance(10000);
QueryWrapper<User> wrapper = new QueryWrapper<User>().eq("username", "张a三");
userMapper.update(user, wrapper);
}
@Test
void textTwo1() {
//基于UpdateWrapper更新id为1,2,3的用户余额减500
UpdateWrapper<User> wrapper = new UpdateWrapper<User>().in("id", 1, 2, 3).setSql("balance = balance - 500");
userMapper.update(null, wrapper);
}
@Test
void 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 {
@Autowired
private IUserService userService;
@Test
void 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);
}
@Test
void testQuery(){
List<User> list = userService.listByIds(List.of(1L, 2L, 3L));
list.forEach(System.out::println);
}
@Test
void 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>