使用 MyBatis-Plus 快速上手(学习笔记)
本文为个人学习 MyBatis-Plus 的笔记,目标是记录从建表、项目初始化到常用 CRUD、条件构造器与分页插件的使用流程与关键注意点。文章以实用示例为主,保留必要说明,便于复现与回顾。
准备工作:建表与环境
建表 SQL
为练习 MyBatis-Plus,先创建一张测试表 u_user(此处主键非自增):
create table u_user
(
id int not null comment '主键(这里非自增)'
primary key,
name varchar(60) null comment '姓名',
age int null comment '年龄',
email varchar(80) null comment '邮箱'
)
comment '学习 MyBatisPlus 而建立的 u_user 表';说明:示例中把
id设为非自增,以便演示手动赋值插入;生产环境中根据业务需要决定是否自增或使用雪花/UUID 等主键策略。
项目与依赖
新建 Spring Boot 项目(示例名:mp-01-first),构建工具为 Maven,JDK 21,Spring Boot 3.x(示例使用 3.5.5)。基础依赖至少包含:
Lombok(减少样板代码)
MySQL 驱动
MyBatis-Plus 的 Spring Boot starter(推荐使用 starter)
在 pom.xml 中加入 MyBatis-Plus starter(必须使用 starter,不要只引入核心包):
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.12</version>
</dependency>提示:直接引入
com.baomidou:mybatis-plus可能不会带上与 Spring Boot 集成所需的类,容易出现@MapperScan或 Spring 自动配置不可用的情况。
数据库配置(application.yml)
示例的 application.yml(请替换用户名/密码与数据库名):
spring
application
namemp-01-first
datasource
driver-class-namecom.mysql.cj.jdbc.Driver
urljdbcmysql//localhost3306/mybatis_plus?useUnicode=true&characterEncoding=utf8&useSSL=false
usernameroot
passwordxxxxxxxxxxxxxxxxxxxxx
hikari
maximum-pool-size10
minimum-idle2
max-lifetime60000
connection-test-queryselect 1
# mapper xml 的位置(mybatis-plus 推荐配置前缀)
mybatis-plus
mapper-locationsclasspathmapper/*.xml
configuration
log-implorg.apache.ibatis.logging.stdout.StdOutImpl说明:
mapper-locations可放在mybatis或mybatis-plus下,但推荐使用mybatis-plus的配置前缀以保持一致。同时log-impl可用于在控制台输出 SQL,便于调试。
实体映射(Entity)
示例实体类 User:
package com.sangui.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* @Author: sangui
* @CreateTime: 2025-08-26
* @Description: user 实体类
* @Version: 1.0
*/
("u_user")
public class User {
("id")
private Integer id;
("name")
private String name;
("age")
private Integer age;
("email")
private String email;
}@TableName:当类名与表名不一致时使用(示例中类名User与表u_user不同)。@TableId:标注主键列(如果列名为id且默认策略可接受,可省略)。@TableField:当字段名与列名一致时通常 可省略;示例为清晰起见显式标注。
Mapper 接口与 @MapperScan
创建 Mapper 接口并继承 BaseMapper<T>,即可获得单表 CRUD 的方法:
package com.sangui.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sangui.domain.User;
public interface UserMapper extends BaseMapper<User> {
}在启动类中开启 mapper 扫描:
package com.sangui;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
("com.sangui.mapper")
public class Mp01FirstApplication {
public static void main(String[] args) {
SpringApplication.run(Mp01FirstApplication.class, args);
}
}注意:
@MapperScan的包路径要与UserMapper所在包一致;使用 MyBatis-Plus starter 后,@MapperScan和 Mapper 的自动注入通常可以正常工作。
基本 CRUD 示例(单表)
插入(insert)
JUnit 测试示例:
void insertTest() {
User user = new User();
user.setId(2);
user.setAge(18);
user.setName("李四");
user.setEmail("lisi@qq.com");
int count = userMapper.insert(user);
System.out.println("数据库改变条数:" + count);
}更新(update)——注意点
示例:
void updateTest() {
User user = new User();
user.setId(3);
user.setAge(199);
user.setName("王五9");
user.setEmail("wangwu9@qq.com");
int count = userMapper.updateById(user);
System.out.println("数据库改变条数:" + count);
}重要说明(关于空值处理):
updateById 会根据实体构建更新语句。若实体中的某些字段为 null,可能会导致数据库列被更新为 NULL(覆盖原值)。如果你需要“选择性更新”(只更新非空字段),应:
在构建实体时只设置需要更新的字段,或
使用
UpdateWrapper/LambdaUpdateWrapper明确指定要更新的列,或使用 MyBatis-Plus 提供的其它配置 / 插件来避免覆盖(例如自定义
MetaObjectHandler、手动判断);
总之,更新行为需在代码中显式控制,避免无意覆盖原有数据。
删除(delete)
void deleteTest(){
int count = userMapper.deleteById(3);
System.out.println("数据库改变条数:" + count);
}查询(select)
void selectTest(){
User user = userMapper.selectById(2);
System.out.println(user);
}自定义 SQL(XML)示例
在 UserMapper 中自定义方法签名:
List<User> selectAll(("myname") String name, ("myage") Integer age);对应的 mapper XML(放在 classpath:mapper/UserMapper.xml):
<mapper namespace="com.sangui.mapper.UserMapper">
<select id="selectAll" resultType="com.sangui.domain.User">
select id,name,email,age
from u_user
where name = #{myname} or age = #{myage}
order by id
</select>
</mapper>测试代码:
void selectAllTest(){
List<User> userList = userMapper.selectAll("张三", 30);
System.out.println(userList);
}条件构造器(QueryWrapper / LambdaQueryWrapper)
MyBatis-Plus 提供 QueryWrapper 与 LambdaQueryWrapper 来构造动态 SQL 的 WHERE 部分,便于链式拼接条件。
等值查询、范围查询、组合查询、排序示例
等值查询:
void selectEqTest(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name","李四");
List<User> userList = userMapper.selectList(wrapper);
System.out.println(userList);
}控制台 SQL 示例:
==> Preparing: SELECT id,name,age,email FROM u_user WHERE (name = ?)between(范围):
void selectBetweenTest(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.between("age",18,19);
List<User> userList = userMapper.selectList(wrapper);
System.out.println(userList);
}SQL:
Preparing: SELECT id,name,age,email FROM u_user WHERE (age BETWEEN ? AND ?)多条件(AND、IN):
void selectAndTest(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age",17).eq("name","李四").in("email","lisi@qq.com","zhangsan@qq.com");
List<User> userList = userMapper.selectList(wrapper);
System.out.println(userList);
}SQL:
==> Preparing: SELECT id,name,age,email FROM u_user WHERE (age > ? AND name = ? AND email IN (?,?))OR 示例:
void selectOrTest(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age",17).or().eq("name","李四");
List<User> userList = userMapper.selectList(wrapper);
System.out.println(userList);
}SQL:
==> Preparing: SELECT id,name,age,email FROM u_user WHERE (age > ? OR name = ?)排序:
void selectOrderTest(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.orderByDesc("age");
List<User> userList = userMapper.selectList(wrapper);
System.out.println(userList);
}分页插件(Paging)配置与使用
引入分页相关依赖(示例):
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.12</version>
</dependency>
<!-- 如需 jsqlparser(部分高级 SQL 分析),按需添加 mybatis-plus-jsqlparser -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-jsqlparser</artifactId>
<version>3.5.12</version>
</dependency>在配置类中注册拦截器(Bean):
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}使用示例:
void selectPageTest(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age",17);
Page<User> userPage = userMapper.selectPage(Page.of(1, 10), wrapper);
System.out.println(userPage);
System.out.println("总页数 = " + userPage.getPages());
System.out.println("每页的大小 = " + userPage.getSize());
System.out.println("总记录条数 = " + userPage.getTotal());
System.out.println("当前页号 = " + userPage.getCurrent());
System.out.println("查询的记录 = " + userPage.getRecords());
}日志与调试建议
在 application.yml 中配置 log-impl(上文已示例)可以把 SQL 输出到控制台,便于检查生成的 SQL。遇到 SQL 不符合预期时:
打印完整 SQL(含参数)并在数据库中执行
EXPLAIN分析性能;对复杂查询优先手写 SQL 并放在 XML 中,便于控制与调优;
对更新操作谨慎处理
null字段,避免误覆盖。
小结与注意事项
使用 starter:在 Spring Boot 项目中应使用 MyBatis-Plus 的 starter,以确保与 Spring Boot 的自动配置正确集成。
实体注解可选:当类名/字段名与数据库一致时,
@TableName/@TableField/@TableId并非强制;但显式标注有利于可读性和后续维护。更新慎重:
updateById与类似 API 的空值覆盖问题需关注;若希望选择性更新,请明确只更新需要的字段或使用 Wrapper。条件构造器灵活:
QueryWrapper与LambdaQueryWrapper支持链式拼接,适合动态查询;但复杂查询建议回退到 XML 手写 SQL 以保证可控性与性能。分页与拦截器:MyBatis-Plus 的分页插件使用简单,建议按需注册并结合
Page对象获取分页信息。学习建议
- 微信
- 赶快加我聊天吧

- 赶快加我聊天吧
