使用SpringBoot+MyBatisPlus实现增删改查
MyBatisPlus教程
一 什么是MyBatisPlus
MyBatis-Plus(简称 MP)是一款基于 MyBatis 的增强工具,旨在简化 MyBatis 的开发流程,提供更高效、更便捷的数据库操作能力。它在 MyBatis 的基础上只做增强不做改变,既保留了 MyBatis 的原生功能,又通过封装常用操作减少了重复代码,让开发者更专注于业务逻辑。
核心特性
- 无侵入性:完全基于 MyBatis 开发,不改变其原有功能,兼容所有 MyBatis 原生特性。
- CRUD 自动生成:通过继承
BaseMapper或IService,无需编写 XML 或 SQL,即可自动获得单表的增删改查(CRUD)操作。 - 条件构造器:提供
QueryWrapper/UpdateWrapper等工具类,通过链式调用快速构建复杂 SQL 条件(如 WHERE、ORDER BY、GROUP BY 等),无需手动拼接 SQL。 - 分页插件:内置分页功能,支持多种数据库(MySQL、Oracle、SQL Server 等),只需简单配置即可实现分页查询。
- 代码生成器:通过配置可自动生成 Entity、Mapper、Service、Controller 等代码,减少重复开发。
- 逻辑删除:通过注解轻松实现逻辑删除(而非物理删除,即通过字段标记数据状态,如
deleted=1表示删除)。 - 乐观锁:提供乐观锁插件,解决并发更新冲突问题(通过版本号字段控制)。
- 多种数据库支持:兼容主流关系型数据库,且支持自定义数据库方言。
优势
- 简化开发:省去大量重复的 SQL 编写和 Mapper 接口方法定义,提高开发效率。
- 降低学习成本:对 MyBatis 用户友好,只需了解 MP 的增强 API 即可快速上手。
- 灵活扩展:支持自定义 SQL、XML 映射文件,可在自动生成的基础上扩展复杂业务逻辑。
适用场景
- 基于 MyBatis 的 Spring/Spring Boot 项目,需要简化数据库操作。
- 单表操作频繁,希望减少 CRUD 代码量的场景。
- 需要快速实现分页、条件查询、逻辑删除等常见功能的项目。
二 环境搭建

1 创建 Maven 项目并添加依赖
创建一个 Maven 项目,项目名为MyBatisPlus-Demo,在 pom.xml 中添加以下依赖:
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- SpringBoot父依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath/>
</parent>
<groupId>com.yqd</groupId>
<artifactId>MyBatisPlus-Demo</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>MyBatisPlus-Demo</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- SpringWeb -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatisPlus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
<scope>runtime</scope>
</dependency>
<!-- Lombok(简化实体类) -->
<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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2 配置数据库连接
在src/main/resources/application.yml中配置数据库信息:
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/springbootdata?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root # 替换为你的数据库用户名
password: 123456 # 替换为你的数据库密码
# MyBatisPlus配置
mybatis-plus:
mapper-locations: classpath:mapper/*.xml # mapper.xml存放路径
type-aliases-package: com.yqd.entity # 实体类包路径
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印SQL日志(可选)
3 导入数据库
-- 创建数据库并设置字符集
CREATE DATABASE IF NOT EXISTS springbootdata;
CHARACTER SET utf8;
COLLATE utf8_unicode_ci;
-- 使用该数据库
USE springbootdata;
-- 创建书籍表(如果不存在)
CREATE TABLE IF NOT EXISTS books (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(200) NOT NULL,
author VARCHAR(100) NOT NULL,
press VARCHAR(100),
status VARCHAR(20)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
三 代码实现
1 创建实体类(Entity)
对应books表创建实体类Book.java:
package com.yqd.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data // Lombok注解,自动生成getter/setter/toString等
@TableName("books") // 对应数据库表名
public class Book {
@TableId(type = IdType.AUTO) // 主键自增
private Long id;
private String name; // 书名
private String author; // 作者
private String press; // 出版社
private String status; // 状态(例如:在架/借出)
}
2 创建 Mapper 接口
继承 MyBatisPlus 的BaseMapper,自动获得基础 CRUD 方法:
package com.yqd.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yqd.entity.Book;
import org.apache.ibatis.annotations.Mapper;
@Mapper // 标记为MyBatis的Mapper接口
public interface BookMapper extends BaseMapper<Book> {
// 无需手动编写CRUD方法,BaseMapper已提供
}
3 创建 Service 层
3.1 Service 接口
package com.yqd.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.yqd.entity.Book;
public interface BookService extends IService<Book> {
// 继承IService,获得更多增强CRUD方法
}
3.2 Service 实现类
package com.yqd.service.impl;
import com.yqd.entity.Book;
import com.yqd.mapper.BookMapper;
import com.yqd.service.BookService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@Service // 标记为服务层组件
public class BookServiceImpl extends ServiceImpl<BookMapper, Book> implements BookService {
// 无需手动实现,ServiceImpl已实现基础方法
}
4 创建 Controller 层(API 接口)
实现增删改查的 HTTP 接口:
package com.yqd.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yqd.entity.Book;
import com.yqd.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/books") // 基础路径
public class BookController {
@Autowired
private BookService bookService;
// 1. 新增书籍
@PostMapping
public boolean addBook(@RequestBody Book book) {
return bookService.save(book);
}
// 2. 删除书籍(根据ID)
@DeleteMapping("/{id}")
public boolean deleteBook(@PathVariable Long id) {
return bookService.removeById(id);
}
// 3. 更新书籍
@PutMapping
public boolean updateBook(@RequestBody Book book) {
return bookService.updateById(book);
}
// 4. 查询单本书籍(根据ID)
@GetMapping("/{id}")
public Book getBookById(@PathVariable Long id) {
return bookService.getById(id);
}
// 5. 查询所有书籍
@GetMapping
public List<Book> getAllBooks() {
return bookService.list();
}
// 6. 条件查询(例如:按作者查询)
@GetMapping("/byAuthor")
public List<Book> getBooksByAuthor(@RequestParam String author) {
QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("author", author); // 等价于 WHERE author = ?
return bookService.list(queryWrapper);
}
// 7. 分页查询
@GetMapping("/page")
public Page<Book> getBooksByPage(
@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize
) {
Page<Book> page = new Page<>(pageNum, pageSize);
return bookService.page(page);
}
// 8. 批量新增书籍
@PostMapping("/batch")
public boolean addBooksBatch(@RequestBody List<Book> books) {
return bookService.saveBatch(books);
}
}
5 配置 MyBatisPlus 分页插件
创建配置类,启用分页功能:
package com.yqd.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisPlusConfig {
// 配置分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 添加分页拦截器
return interceptor;
}
}
6 启动类
package com.yqd;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(value = {"com.yqd.mapper"})
public class MyBatisPlusDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MyBatisPlusDemoApplication.class, args);
}
}
四 系统测试
4.1 测试环境准备
- 启动 SpringBoot 项目,确保服务运行在
http://localhost:8080 - 数据库已初始化
springbootdata库和books表 - 安装 Postman(或使用其他 API 测试工具,如 curl、Apifox 等)
4.2 测试步骤及示例
1. 新增书籍(单条)
-
请求方式:
POST -
请求地址:
http://localhost:8080/books -
请求头:
Content-Type: application/json -
请求体(JSON)
{ "name": "红楼梦", "author": "曹雪芹", "press": "人民文学出版社", "status": "在架" } -
预期响应:
true(表示新增成功)
2. 批量新增书籍
-
请求方式:
POST -
请求地址:
http://localhost:8080/books/batch(需提前在 Controller 中添加批量接口,见前文) -
请求头:
Content-Type: application/json -
请求体(JSON 数组)
[ { "name": "三国演义", "author": "罗贯中", "press": "中华书局", "status": "在架" }, { "name": "水浒传", "author": "施耐庵", "press": "人民文学出版社", "status": "借出" }, { "name": "西游记", "author": "吴承恩", "press": "中华书局", "status": "在架" } ] -
预期响应:
true(表示批量新增成功)
3. 查询所有书籍
-
请求方式:
GET -
请求地址:
http://localhost:8080/books -
预期响应
:返回包含所有书籍的 JSON 数组,例如:
[ { "id": 1, "name": "红楼梦", "author": "曹雪芹", "press": "人民文学出版社", "status": "在架" }, { "id": 2, "name": "三国演义", "author": "罗贯中", "press": "中华书局", "status": "在架" } ]
4. 查询单本书籍(按 ID)
-
请求方式:
GET -
请求地址:
http://localhost:8080/books/1(假设 ID=1 的书籍存在) -
预期响应
:返回 ID=1 的书籍详情:
{ "id": 1, "name": "红楼梦", "author": "曹雪芹", "press": "人民文学出版社", "status": "在架" }
5. 条件查询(按作者)
-
请求方式:
GET -
请求地址:
http://localhost:8080/books/byAuthor?author=罗贯中 -
预期响应
:返回所有作者为 “罗贯中” 的书籍:
[ { "id": 2, "name": "三国演义", "author": "罗贯中", "press": "中华书局", "status": "在架" } ]
6. 分页查询
-
请求方式:
GET -
请求地址:
http://localhost:8080/books/page?pageNum=1&pageSize=2(第 1 页,每页 2 条) -
预期响应
:返回分页结果(包含总条数、当前页数据等):
{ "records": [ { "id": 1, "name": "红楼梦", "author": "曹雪芹", "press": "人民文学出版社", "status": "在架" }, { "id": 2, "name": "三国演义", "author": "罗贯中", "press": "中华书局", "status": "在架" } ], "total": 3, // 总条数 "size": 2, // 每页条数 "current": 1, // 当前页 "pages": 2 // 总页数 }
7. 更新书籍
-
请求方式:
PUT -
请求地址:
http://localhost:8080/books -
请求头:
Content-Type: application/json -
请求体(JSON):(修改 ID=1 的书籍状态为 “借出”)
{ "id": 1, "name": "红楼梦", "author": "曹雪芹", "press": "人民文学出版社", "status": "借出" } -
预期响应:
true(表示更新成功) -
验证:调用 “查询单本书籍(ID=1)” 接口,确认
status已改为 “借出”。
8. 删除书籍
- 请求方式:
DELETE - 请求地址:
http://localhost:8080/books/3(删除 ID=3 的书籍) - 预期响应:
true(表示删除成功) - 验证:调用 “查询所有书籍” 接口,确认 ID=3 的书籍已不存在。
4.3 测试注意事项
- 依赖顺序:部分接口依赖前置操作(例如 “更新” 和 “删除” 需要先有数据,需先执行 “新增”)。
- 参数正确性
- 新增 / 更新时,
name和author为非空字段,若为空会返回false(需在后端添加校验优化,此处仅为基础测试)。 - 分页查询的
pageNum和pageSize需为正整数。
- 新增 / 更新时,
- 错误场景测试
- 查询不存在的 ID(如
http://localhost:8080/books/999),预期返回null。 - 删除不存在的 ID,预期返回
false。
- 查询不存在的 ID(如

浙公网安备 33010602011771号