一、MyBatis-Plus简介
1.1、介绍
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生,官网地址:https://baomidou.com/

1.2、特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
1.3、支持数据库

任何能使用 MyBatis 进行增删改查,并且支持标准 SQL 的数据库应该都在 MyBatis-Plus 的支持范围内
1.4、框架结构

二、MyBatis-Plus快速上手
2.1、数据准备
此处依旧采用前篇我们已有的数据库用户表(创建表的SQL语句见前篇):

2.2、项目配置
创建springboot项目,添加如图所示的依赖即可:

maven中根据 spring boot 的版本添加依赖:
Spring Boot 3:
XML
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.5</version>
</dependency>
Spring Boot 2:
XML
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.7</version>
</dependency>
配置数据库:
XML
# 数据库连接配置
datasource:
url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
2.3、创建实体类
创建实体类UserInfo
java
@Data
public class UserInfo {
private Integer id;
private String username;
private String password;
private Integer age;
private Integer gender;
private String phone;
private Integer deleteFlag;
private Date createTime;
private Date updateTime;
}
编写mapper接口类

进入BaseMapper类查看源码:
java
public interface BaseMapper<T> extends Mapper<T> {
int insert(T entity);
int deleteById(Serializable id);
int deleteById(T entity);
...
}
该类接收一个泛型参数作为操作对象,因此需要将UserInfo 传入BaseMapper 的**<>**括号中
MyBatis-Plus 提供了基础的 BaseMapper 接口,该接口已实现单表 CRUD 操作。我们只需让自定义的 Mapper 继承 BaseMapper,即可直接使用这些基础功能,无需自行实现单表增删改查操作

2.4、单元测试(CRUD)
java
@SpringBootTest
public class MyBatisplusTests {
@Autowired
private UserInfoMapper userInfoMapper;
@Test
void testSelectByIds(){
List<UserInfo> list=userInfoMapper.selectBatchIds(List.of(10,11,12));
list.forEach(System.out::println);
}
@Test
void testInsert(){
UserInfo userInfo=new UserInfo();
userInfo.setId(15);
userInfo.setAge(35);
userInfo.setPassword("123456");
userInfo.setGender(1);
userInfo.setUsername("程序员");
userInfo.setPhone("10010010011");
userInfoMapper.insert(userInfo);
}
@Test
void testUpdate(){
UserInfo userInfo=new UserInfo();
userInfo.setId(13);
userInfo.setPhone("20022002200");
userInfoMapper.updateById(userInfo);
}
}
运行结果;


三、MyBatis-Plus复杂操作
3.1、主要注解
UserInfoMapper 继承 BaseMapper 时需指定泛型类型 ,这里的 UserInfo 就是与数据库表对应的实体类,MyBatis-Plus 会根据该实体类自动推断表结构信息
默认映射规则如下:
- 表名:将实体类的驼峰命名转换为下划线命名(如 UserInfo → user_info)
- 字段:将属性名的驼峰命名转换为下划线命名(如 deleteFlag → delete_flag)
- 主键:默认使用 id 字段
若实体类与数据库表结构不符合上述默认规则,MyBatis-Plus 提供了多种注解来显式指定映射关系:
3.1.1、@TableName
那么我们根据上述规则进行修改实体类的名称:UserInfo -> Userinfo ,再次执行查询操作:

这种情况我们就可以通过**@TableName注解来标识实体类对应的表**:


3.1.2、@TableField
@TableName注解来标识实体类对应的表,那么@TableField这个注解就是用来标识属性对应的字段名
3.1.3、@TableId
@TableId注解用来指定属性对应的主键
当属性名与数据库字段名不一致时,需在@TableId 注解中明确指定对应字段名;若两者一致,则直接使用@TableId 注解即可
3.2、配置日志
XML
mybatis-plus:
configuration: # 配置打印 MyBatis⽇志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3.3、条件构造器
MyBatis-Plus也提供了强大的条件构造器(Wrapper )来支持复杂查询场景。这套Wrapper机制允许开发者通过链式调用方式构建查询条件,既能提升开发效率,又能有效避免SQL注入风险
条件构造器😄MyBatis-Plus提供的主要Wrapper类及其功能包括:
- AbstractWrapper:所有Wrapper类的基类,封装了通用的查询条件构建方法
- QueryWrapper:专用于查询条件的构造,在AbstractWrapper基础上扩展了select方法用于指定查询字段
- UpdateWrapper:用于构建更新操作的条件
- LambdaQueryWrapper:基于Lambda表达式的查询构造器,通过实体类属性引用避免字段名硬编码
- LambdaUpdateWrapper:基于Lambda表达式的更新构造器,同样避免字段名硬编码问题
3.3.1、QueryWrapper
QueryWrapper不仅适用于查询语句,还可用于构建修改、删除等操作的查询条件
查:
java
@Test
void testQueryWrapper(){
QueryWrapper<Userinfo> queryWrapper=new QueryWrapper<Userinfo>()
.select("id","username","age","phone")
.eq("age",18)
.like("phone","19");
List<Userinfo> list=userInfoMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}

请注意:
默认情况下,Mybatis-Plus会根据@TableField 注解自动生成字段别名。但如果指定了QueryWrapper的 select 属性,查询结果将仅包含属性值而丢失别名,导致结果映射失败
正常查询:
java@Test void testQueryWrapper2(){ QueryWrapper<Userinfo> wrapper = new QueryWrapper<>(); List<Userinfo> users = userInfoMapper.selectList(wrapper); users.forEach(System.out::println); }
指定select时:
java@Test void testQueryWrapper2(){ QueryWrapper<Userinfo> wrapper = new QueryWrapper<>(); wrapper.select("create_time"); // 明确指定查询字段 List<Userinfo> users = userInfoMapper.selectList(wrapper); users.forEach(System.out::println); }
查询仅包含 create_time 字段,但返回类型为 UserInfo,导致打印结果中其他属性值均为 null
解决方案:
- 手动编写自定义SQL
- 确保实体类属性名与数据库列名完全一致
- 避免在QueryWrapper中显式指定select 字段
- 改用LambdaQueryWrapper进行查询
改:

java
@Test
void testQueryWrapper3(){
QueryWrapper<Userinfo> wrapper = new QueryWrapper<Userinfo>()
.lt("age",16);
Userinfo userinfo=new Userinfo();
userinfo.setPhone("00000000000");
userInfoMapper.update(userinfo,wrapper);
}
- lt - "less than" 的缩写,表示"小于"
- le - "less than or equal to" 的缩写,表示"小于等于"
- ge - "greater than or equal to" 的缩写,表示"大于等于"
- gt - "greater than" 的缩写,表示"大于"
- eq - "equals" 的缩写,表示"等于"
- ne - "not equals" 的缩写,表示"不等于"
删:
java
@Test
void testQueryWrapper4(){
QueryWrapper<Userinfo> wrapper = new QueryWrapper<Userinfo>()
.eq("delete_flag",1);
userInfoMapper.delete(wrapper);
}
3.3.2、UpdateWrapper
我们可以直接使用 UpdateWrapper 进行更新操作,无需创建实体对象即可直接设置更新字段和条件
基础更新:

java
@Test
void testUpdateByUpdateWrapper(){
UpdateWrapper<Userinfo> updateWrapper = new UpdateWrapper<Userinfo>()
.set("delete_flag",0)
.set("age", 5)
.in("id", List.of(1,2,3));
userInfoMapper.update(updateWrapper);
}
基于SQL更新:
java
@Test
void testUpdateBySQLUpdateWrapper(){
UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>()
.setSql("age = age+10")
.in("id", List.of(1,2,3));
userInfoMapper.update(updateWrapper);
}
3.3.3、LambdaQueryWrapper
使用QueryWrapper 和UpdateWrapper时存在一个明显问题:需要手动编写字段名称字符串。如果数据库字段名称发生变更,由于测试覆盖不足,很容易引发生产事故
MyBatis-Plus提供了基于Lambda 表达式的条件构造器解决方案,通过Lambda 表达式引用实体类属性,完美解决了字段名硬编码问题。这种方式不仅提升了代码可读性,也显著增强了代码的可维护性
主要实现类包括:
- LambdaQueryWrapper
- LambdaUpdateWrapper
这两个类分别对应传统的QueryWrapper 和UpdateWrapper功能
java
@Test
void testQueryWrapper5(){
QueryWrapper<Userinfo> queryWrapper=new QueryWrapper<Userinfo>();
queryWrapper.lambda().select(Userinfo::getId , Userinfo::getAge,
Userinfo::getUsername , Userinfo::getPhone)
.eq(Userinfo::getAge,18)
.like(Userinfo::getPhone,"19");
List<Userinfo> list=userInfoMapper.selectList(queryWrapper);
list.forEach(System.out::println);
}

3.3.4、LambdaUpdateWrapper
java
@Test
void testLambdUpdateByUpdateWrapper(){
UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>();
updateWrapper.lambda()
.set(UserInfo::getDeleteFlag, 0)
.set(UserInfo::getAge, 5)
.in(UserInfo::getUserId, List.of(1,2,3));
userInfoMapper.update(updateWrapper);
}
or 方法是 MyBatis-Plus 提供的核心查询构造方法之一,主要用于实现 OR 逻辑查询条件。该方法会改变后续查询条件的连接方式,将默认的 AND 连接转换为 OR 连接

3.4、自定义SQL
当MyBatis-Plus提供的标准操作无法满足我们的需求时,我们可以利用其提供的自定义SQL功能;通过Wrapper构建查询条件,再配合Mapper编写SQL语句,就能灵活实现各种复杂查询需求


java
---------------mapper------------------
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
@Select("select id,username,password,age FROM user_info ${ew.customSqlSegment}")
List<UserInfo> queryUserByCustom(@Param(Constants.WRAPPER) Wrapper<UserInfo> wrapper);
}
---------------test--------------------
@Test
void testQueryUserByCustom(){
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>()
.eq("username","admin");
userInfoMapper.queryUserByCustom(queryWrapper).forEach(System.out::println);
}
注意事项:
- 参数命名 :在自定义 SQL 时,若需传递 Wrapper 对象作为参数,必须使用
ew
作为参数名,或者通过@Param(Constants.WRAPPER)
注解明确指定该参数为 Wrapper 对象 - 使用方式 :在 SQL 语句中,通过
${ew.customSqlSegment}
来引用 Wrapper 对象生成的 SQL 片段 - 功能限制:使用自定义 SQL 时,Wrapper 对象不会基于实体类自动生成 where 子句,需要手动编写完整的 SQL 语句