MyBatis-Plus 从入门到 CRUD 实战:Spring Boot 整合

一、为什么要用 MyBatis-Plus?

什么是 MyBatis-Plus?

官方定位 :MyBatis-Plus 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

它提供了通用 Mapper 和通用 Service,可以在不编写任何 SQL 语句的前提下,快速实现单表的增删改查(CRUD)、批量、逻辑删除、分页等操作。

核心特性一览

复制代码
flowchart LR

subgraph 传统开发

A1[手写 Entity] --> A2[手写 Mapper 接口]

A2 --> A3[手写 Mapper.xml SQL]

A3 --> A4[手写 Service]

end

subgraph MP开发

B1[实体类] --> B2[继承 BaseMapper]

B2 --> B3[自动注入全部CRUD<br/>无需写SQL]

B3 --> B4[继承 IService 获得<br/>通用业务方法]

end

A1 -.只做增强不做改变.-> B1

|---------------|-------------------------------------------|
| 特性 | 说明 |
| 无侵入 | 只做增强不做改变,引入它不会对现有工程产生影响 |
| 损耗小 | 启动即自动注入基本 CRUD,性能基本无损耗,直接面向对象操作 |
| 强大的 CRUD | 内置通用 Mapper、通用 Service,少量配置即可实现单表大部分 CRUD |
| 支持 Lambda | 通过 Lambda 表达式编写查询条件,不用担心字段写错 |
| 主键自动生成 | 支持多种主键策略(内含分布式唯一 ID 生成器) |
| 内置代码生成器 | 快速生成 Mapper、Model、Service、Controller 层代码 |
| 内置分页插件 | 基于 MyBatis 物理分页,写分页等同普通 List 查询 |
| 内置性能分析插件 | 可输出 SQL 及执行时间,快速揪出慢查询 |
| 内置全局拦截插件 | 提供全表 delete/update 智能分析阻断,预防误操作 |

支持哪些数据库?

任何能使用 MyBatis 进行 CRUD、并支持标准 SQL 的数据库都支持,包括:

MySQL、Oracle、DB2、H2、HSQL、SQLite、PostgreSQL、SQLServer、Phoenix、Gauss、ClickHouse、Sybase、OceanBase、达梦、人大金仓等。

二、开发环境准备

|--------------|---------------|
| 组件 | 版本 |
| IDE | IntelliJ IDEA |
| JDK | JDK 8+ |
| 构建工具 | Maven 3.5.4 |
| 数据库 | MySQL 5.7 |
| Spring Boot | 2.6.3 |
| MyBatis-Plus | 3.5.1 |


三、快速入门:跑通第一个查询

创建数据库及表

复制代码
CREATE DATABASE `mybatis_plus` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;

USE `mybatis_plus`;



CREATE TABLE `user` (

`id` bigint(20) NOT NULL COMMENT '主键ID',

`name` varchar(30) DEFAULT NULL COMMENT '姓名',

`age` int(11) DEFAULT NULL COMMENT '年龄',

`email` varchar(50) DEFAULT NULL COMMENT '邮箱',

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- 插入测试数据

INSERT INTO user (id, name, age, email) VALUES

(1, 'Jone', 18, 'test1@baomidou.com'),

(2, 'Jack', 20, 'test2@baomidou.com'),

(3, 'Tom', 28, 'test3@baomidou.com'),

(4, 'Sandy', 21, 'test4@baomidou.com'),

(5, 'Billie', 24, 'test5@baomidou.com');

初始化 Spring Boot 工程并引入依赖

复制代码
<dependencies>

<!-- Spring Boot 基础 -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

</dependency>

<!-- MyBatis-Plus 核心依赖 -->

<dependency>

<groupId>com.baomidou</groupId>

<artifactId>mybatis-plus-boot-starter</artifactId>

<version>3.5.1</version>

</dependency>

<!-- Lombok -->

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

<optional>true</optional>

</dependency>

<!-- MySQL 驱动 -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<scope>runtime</scope>

</dependency>

</dependencies>

配置 application.yml

复制代码
spring:

datasource:

type: com.zaxxer.hikari.HikariDataSource

driver-class-name: com.mysql.cj.jdbc.Driver

url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false

username: root

password: 123456

踩坑提醒

  1. 驱动类:Spring Boot 2.0(内置 JDBC5)用 com.mysql.jdbc.Driver;2.1 及以上(内置 JDBC8)用 com.mysql.cj.jdbc.Driver,否则测试会有 WARN。
  2. URL:MySQL 8.0 需要加 serverTimezone=GMT%2B8,否则报 The server time zone value ... is unrecognized。

编写启动类、实体、Mapper

复制代码
// 启动类:扫描 mapper 包

@SpringBootApplication

@MapperScan("com.qcby.mybatisplus.mapper")

public class MybatisplusApplication {

public static void main(String[] args) {

SpringApplication.run(MybatisplusApplication.class, args);

}

}

// 实体类:使用 Lombok 简化

@Data

public class User {

private Long id;

private String name;

private Integer age;

private String email;

}

// Mapper 接口:继承 BaseMapper<User>,即拥有全部 CRUD

public interface UserMapper extends BaseMapper<User> {

}

测试:一个方法查全部

复制代码
@SpringBootTest

public class MybatisPlusTest {



@Autowired

private UserMapper userMapper;



@Test

public void testSelectList() {

// selectList() 根据条件构造器查询一个 list 集合,null 表示无条件,即查询所有

userMapper.selectList(null).forEach(System.out::println);

}

}

运行后即可打印出全部 5 条用户数据。注意:IDEA 可能提示 userMapper 找不到注入对象(类是动态创建的),程序其实能正常运行;为了避免报错提示,可在 Mapper 接口上添加 @Repository 注解。

开启 SQL 日志

复制代码
mybatis-plus:

configuration:

# 控制台打印 MyBatis 执行的 SQL,便于调试

log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

四、基本 CRUD:BaseMapper 全掌握

BaseMapper<T> 内置了全部单表 CRUD 方法,直接继承即可使用。核心方法如下:

|----|---------------------------------|-------------|
| 操作 | 方法 | 说明 |
| 插入 | int insert(T entity) | 插入一条记录 |
| 删除 | int deleteById(Serializable id) | 根据 ID 删除 |
| 删除 | int deleteBatchIds(...) | 根据 ID 批量删除 |
| 删除 | int deleteByMap(Map) | 根据 map 条件删除 |
| 删除 | int delete(Wrapper) | 根据条件构造器删除 |
| 修改 | int updateById(T entity) | 根据 ID 修改 |
| 修改 | int update(T, Wrapper) | 根据条件更新 |
| 查询 | T selectById(Serializable id) | 根据 ID 查询 |
| 查询 | List<T> selectBatchIds(...) | 根据多个 ID 查询 |
| 查询 | List<T> selectList(Wrapper) | 查询全部/按条件 |
| 查询 | Long selectCount(Wrapper) | 查询总记录数 |
| 查询 | List<Map> selectMaps(Wrapper) | 查询返回 Map |
| 分页 | IPage selectPage(page, wrapper) | 分页查询 |

插入

复制代码
@Test

public void testInsert() {

User user = new User(null, "张三", 23, "zhangsan@qcby.com");

// 执行: INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )

int result = userMapper.insert(user);

System.out.println("受影响行数:" + result);

// 打印自动生成的 id: 1475754982694199298

System.out.println("id自动获取:" + user.getId());

}

知识点 :插入时 id 自动生成为 1475754982694199298 这类超长数字------这是 MyBatis-Plus 默认基于雪花算法生成的主键。

删除(三种方式)

复制代码
// 方式一:根据 id 删除

int result = userMapper.deleteById(1475754982694199298L);

// 方式二:根据多个 id 批量删除

int result = userMapper.deleteBatchIds(Arrays.asList(1L, 2L, 3L));

// 方式三:根据 map 条件删除(map 的 key 是字段名,value 是值)

Map<String, Object> map = new HashMap<>();

map.put("age", 23);

map.put("name", "张三");

int result = userMapper.deleteByMap(map); // DELETE FROM user WHERE name = ? AND age = ?

修改

复制代码
@Test

public void testUpdateById() {

User user = new User(4L, "admin", 22, null);

// 只更新非 null 字段: UPDATE user SET name=?, age=? WHERE id=?

int result = userMapper.updateById(user);

}

重要特性 :updateById 只更新实体中非 null 的字段。email 传 null 不会被更新。

查询(四种方式)

复制代码
// 方式一:根据 id 查询

User user = userMapper.selectById(4L);



// 方式二:根据多个 id 查询

List<User> list = userMapper.selectBatchIds(Arrays.asList(4L, 5L));



// 方式三:根据 map 条件查询

Map<String, Object> map = new HashMap<>();

map.put("age", 22);

map.put("name", "admin");

List<User> list = userMapper.selectByMap(map);



// 方式四:查询所有(null 表示无条件)

List<User> list = userMapper.selectList(null);

通过观察 BaseMapper 的方法,大多方法都有 Wrapper 类型的形参------这就是条件构造器,可针对 SQL 设置不同条件;若无条件,传 null 即查询/删除/修改所有数据。


五、通用 Service:业务层封装

基础 Mapper 属于 DAO 层,业务层还有一个更常用的封装------IService / ServiceImpl

创建 Service 接口和实现类

复制代码
// 接口:继承 IService<User>,获得通用业务方法

public interface UserService extends IService<User> {

}



// 实现类:继承 ServiceImpl<UserMapper, User>,获得基础实现

@Service

public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

}

测试:查询记录数 & 批量插入

复制代码
@Autowired

private UserService userService;



@Test

public void testGetCount() {

long count = userService.count();

System.out.println("总记录数:" + count);

}



@Test

public void testSaveBatch() {

// SQL 长度有限制,海量数据无法用单条 SQL 插入,

// 因此 MP 将批量插入放在通用 Service 实现,而非通用 Mapper

List<User> users = new ArrayList<>();

for (int i = 0; i < 5; i++) {

User user = new User();

user.setName("szy" + i);

user.setAge(20 + i);

users.add(user);

}

userService.saveBatch(users); // 批量插入

}

命名规范:通用 Service CRUD 采用 get(查询单行)、remove(删除)、list(查询集合)、page(分页)前缀命名,与 Mapper 层区分避免混淆。若需要自定义通用方法,建议创建自己的 IBaseService 继承 MP 提供的基类。


六、常用注解深入讲解

经过前面的测试,我们没指定操作哪张表,只是 Mapper 继承 BaseMapper 时设置了泛型 User,MP 就自动操作了 user 表。**这说明 MP 操作的表由泛型(实体类型)决定,默认表名 = 实体类名。**但真实开发中会遇到各种"不一致",就要靠注解解决。

@TableName:实体类名 ≠ 表名

问题:把表 user 改名为 t_user 后,查询报错 Table 'mybatis_plus.user' doesn't exist。

解决方式一(注解):在实体类上标注对应表名

复制代码
@TableName("t_user")

@Data

public class User { ... }

解决方式二(全局配置):开发中常遇到表都有固定前缀(如 t_),可统一配置,无需每个实体类标注

复制代码
mybatis-plus:

global-config:

db-config:

# 配置操作表的默认前缀

table-prefix: t_

@TableId:主键不是 id,或需要指定主键策略

问题:若实体的主键字段叫 uid 而非 id,MP 不会自动识别,报 Field 'uid' doesn't have a default value。

解决方式:用 @TableId 标识主键

复制代码
@Data

public class User {

@TableId

private Long uid;

...

}

value 属性:当实体主键属性是 id、但表主键字段是 uid 时:

复制代码
@TableId("uid") // 或 @TableId(value = "uid")

private Long id;

type 属性(主键策略)

|----------------------|------------------------|
| 值 | 描述 |
| IdType.ASSIGN_ID(默认) | 基于雪花算法生成 id,与数据库是否自增无关 |
| IdType.AUTO | 使用数据库自增,需确保数据库设置了自增 |

配置全局主键策略:

复制代码
mybatis-plus:

global-config:

db-config:

id-type: auto # 全局使用数据库自增

@TableField:属性名 ≠ 字段名

情况 1(驼峰 vs 下划线) :实体属性 userName、表字段 user_name。MP 默认自动将下划线转驼峰,无需处理。

情况 2(不满足映射规则):实体属性 name、表字段 username。需用注解指定字段名:

复制代码
@Data

public class User {

@TableField("username")

private String name;

...

}

@TableLogic:逻辑删除

物理删除 vs 逻辑删除

  • 物理删除:真实删除数据,之后查不到;
  • 逻辑删除 :假删除,把"是否删除"状态字段改为已删除,数据库仍保留记录,可数据恢复

实现三步走

  1. 数据库加逻辑删除列 is_deleted,默认值 0;
  1. 实体类加对应属性并标 @TableLogic;
  1. 测试:删除操作实际执行的是修改,查询会自动过滤已删除数据。

    @Data

    public class User {

    ...

    @TableLogic

    private Integer isDeleted;

    }

执行效果(自动生成的 SQL):

复制代码
删除时实际执行修改

UPDATE t_user SET is_deleted=1 WHERE id=? AND is_deleted=0

查询时自动过滤已删除

SELECT ... FROM t_user WHERE is_deleted=0

七、总结

回顾本文,你已经掌握了 MyBatis-Plus 最核心的入门能力:

  1. 环境搭建:Spring Boot + MP 3.5.1 + Lombok + MySQL,跑通第一个查询;
  1. 基础 CRUD:BaseMapper 内置全部单表增删改查,updateById 只更新非 null 字段;
  1. 通用 Service:IService / ServiceImpl 封装业务层,支持 count、saveBatch 等;
  1. 常用注解:@TableName 解决表名、@TableId 解决主键与策略、@TableField 解决字段映射、@TableLogic 实现逻辑删除。
相关推荐
振宇i2 个月前
springcloudAlibaba2025.0.0.0组件版本对应关系
springcloud·mybatis-plus·依赖关系
skywalker_113 个月前
SpringBoot速通(实战教学)
java·spring boot·redis·rpc·ssm·mybatis-plus
段ヤシ.4 个月前
回顾Java知识点,面试题汇总Day17(持续更新)
java·springboot·spring security·shiro·mybatis-plus·jdbctemplate·spring data jpa
Mahir084 个月前
MyBatis 分页与插件深度解密:从插件机制到三大分页方案原理全解
java·后端·mybatis·mybatis-plus·大厂面试题
谷哥的小弟4 个月前
图文详解Spring Boot整合MyBatisPlus(附源码)
mybatis·源码·springboot·mybatis-plus·整合
递归尽头是星辰5 个月前
Java类型安全查询框架体系:QueryDSL、Ebean、jOOQ、MyBatis-Plus
mybatis-plus·querydsl·ebean·jooq·动态 sql
稻草猫.6 个月前
MyBatis-Plus高效开发全攻略
java·数据库·后端·spring·java-ee·mybatis·mybatis-plus
为美好的生活献上中指6 个月前
*Java 沉淀重走长征路*之——《MyBatis与MyBatis-Plus一文打尽!》
java·jvm·maven·mybatis·mybatis-plus
Sun 32856 个月前
MyBatis-Plus 新版代码生成器的使用
java·spring boot·后端·spring·配置·mybatis-plus·代码生成器