MyBatis-Plus 笔记一
一、MyBatis-Plus 基础概述
1. 简介
MyBatis-Plus(简称MP)是国内苞米豆团队开发的MyBatis增强工具 ,核心宗旨:只做增强、不做修改 ,无缝兼容原有MyBatis项目,引入后不会破坏现有代码逻辑,主打简化单表CRUD开发、提升开发效率。
核心定位:MyBatis最佳搭档,像双人搭档一样大幅减少重复代码。
2. 核心五大特性
- 无侵入:纯增强,原有MyBatis代码完全不用改动,平滑接入;
- 损耗极小:项目启动自动注入基础CRUD,无额外性能开销,直接面向实体对象操作;
- 内置强大CRUD:通用Mapper、通用Service开箱即用,搭配条件构造器覆盖绝大多数单表查询场景;
- Lambda表达式支持:通过Lambda写查询条件,彻底杜绝手写数据库字段名写错的bug;
- 丰富配套功能:主键自动生成、代码生成器、物理分页、性能分析、全局拦截、逻辑删除、乐观锁一站式支持。
3. 支持数据库
兼容所有能使用MyBatis的标准SQL数据库,除MySQL、Oracle、SQLServer外,还适配国产数据库:达梦、人大金仓、南大通用、瀚高、OceanBase、ClickHouse等。
4. 框架执行流程&组件拆分
(1)五大核心组件
mybatis-plus-boot-starter:SpringBoot场景启动器,整合所有功能;annotation:全套注解(@TableName、@TableId、@TableField等);extension:扩展插件(分页、乐观锁、逻辑删除、性能分析插件);core:核心底层,CRUD底层封装、SQL自动生成逻辑;generator:代码生成器,一键生成Mapper/Entity/Service/Controller。
(2)底层自动执行流程
- 扫描实体类:项目启动时自动扫描所有实体POJO;
- 反射解析:通过反射读取实体类名、属性名,映射数据库表名、字段名;
- 自动生成SQL:动态拼接insert/update/delete/select基础SQL;
- 注入MyBatis容器:把生成好的SQL语句注册到MyBatis,无需手动写XML。
二、SpringBoot快速上手Demo
前置准备
- 安装Java环境、IDEA,熟悉SpringBoot、Maven基础;
- 创建测试数据库与user表。
1. 数据库建表+测试数据
sql
DROP TABLE IF EXISTS user;
CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
-- 插入测试数据
DELETE FROM user;
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');
2. Maven依赖引入
新建SpringBoot项目,导入核心依赖,不要同时引入原生MyBatis,会冲突:
xml
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<!-- Lombok简化实体类 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- MyBatis-Plus SpringBoot启动器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
3. 配置文件 application.yml(推荐)
yaml
# 数据源配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/boot?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: root
password: root
# MyBatis-Plus配置
mybatis-plus:
# 打印执行SQL日志,开发环境必备
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
4. 实体类POJO编写
java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
补充:如果实体类名和数据库表名不一致、字段名不一致,需要用注解映射,下文注解部分详细说明。
5. Mapper接口(核心:继承BaseMapper)
java
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
// BaseMapper已经内置全部单表CRUD方法,无需手写SQL/XML
}
6. 启动类配置Mapper扫描
两种二选一:
- 启动类加
@MapperScan(推荐,多个Mapper不用每个加@Mapper)
java
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.mp.mapper") // 扫描mapper包路径
@SpringBootApplication
public class SmpApplication {
public static void main(String[] args) {
SpringApplication.run(SmpApplication.class, args);
}
}
- 每个Mapper接口单独添加
@Mapper注解,无需启动类扫描。
7. 测试查询全部数据
java
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class SmpApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void testSelectAll() {
// 参数Wrapper为null代表无查询条件,查询全表
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
}
运行后直接打印5条用户数据,全程零XML、零SQL语句,极简开发。
三、MyBatis-Plus 核心常用注解
1. @TableName 表名注解
作用:实体类和数据库表名不一致时手动绑定表名,标注在实体类上。
java
@TableName("sys_user") // 实体User对应数据库sys_user表
public class User {
private Long id;
// ...
}
常用属性:
value:指定数据库表名;excludeProperty:排除实体中不需要映射到数据库的字段。
2. @TableId 主键注解(重点,关联ID生成策略)
标注在主键字段上,用于声明主键、配置主键生成规则。
java
public class User {
@TableId(type = IdType.AUTO)
private Long id;
// ...
}
核心属性type对应IdType枚举,后文ID生成方式详细拆解。
3. @TableField 普通字段注解(非主键)
场景:实体属性名和数据库列名不一致、字段不参与查询、自动填充、逻辑字段等。
示例:
java
// 数据库字段user_name,实体属性name
@TableField(value = "user_name")
private String name;
// 该字段只插入不查询
@TableField(select = false)
private String password;
// 更新时自动执行 age = age + 1
@TableField(update = "%s+1")
private Integer age;
关键属性:
value:映射数据库字段名;exist:false代表该属性不是数据库字段;fill:自动填充策略(插入填充、更新填充、插入更新都填充)。
4. @TableLogic 逻辑删除注解
标记逻辑删除字段,配合全局配置实现软删除;
5. @Version 乐观锁版本号注解
用于并发更新防覆盖;
6. @OrderBy 默认排序注解
实体查询时默认排序,优先级低于代码中写的Wrapper条件;
7. @EnumValue 枚举映射注解
实体枚举字段和数据库数值映射。
四、重中之重:MyBatis-Plus 主键ID生成全详解
1. IdType 全部枚举类型说明
java
public enum IdType {
AUTO(0), // 数据库自增
NONE(1), // 未设置主键,跟随全局配置
INPUT(2), // 手动输入主键,插入前代码赋值
ASSIGN_ID(3),// 雪花算法,支持Long/String类型(官方推荐)
ASSIGN_UUID(4),// UUID字符串
// 以下均为废弃旧版本写法,统一用ASSIGN_ID/ASSIGN_UUID替代
@Deprecated ID_WORKER(3),
@Deprecated ID_WORKER_STR(3),
@Deprecated UUID(4);
}
2. 五种ID生成方式完整讲解
方式1:AUTO 数据库自增主键
适用场景 :单体项目、单库,无分布式场景;
实现步骤:
- 数据库主键id字段设置
auto_increment自增约束; - 实体主键注解指定类型:
java
@TableId(type = IdType.AUTO)
private Long id;
执行逻辑 :插入数据时,数据库自动生成自增id,插入完成后自动回填到实体对象中;
缺点:分库分表、分布式多节点环境下会出现ID重复,不适合微服务。
方式2:INPUT 手动输入主键
适用场景 :自定义主键、Redis预生成全局ID、外部系统传入主键;
实现步骤:
- 注解配置:
java
@TableId(type = IdType.INPUT)
private Long id;
- 插入数据前必须手动给id赋值,否则数据库报主键为空:
java
User user = new User();
user.setId(10001L); // 手动赋值主键
user.setName("测试用户");
userMapper.insert(user);
特点:MP不会自动生成ID,完全由开发者控制主键值。
方式3:ASSIGN_ID 雪花算法(官方默认、分布式首选)
(1)雪花算法原理(SnowFlake)
Twitter开源分布式唯一ID算法,生成64位Long型数字,结构拆分:
- 1位符号位:固定0,保证正数;
- 41位时间戳:毫秒级,可使用69年;
- 10位机器ID:5位数据中心ID + 5位机器节点ID,最多支持1024台服务;
- 12位毫秒内序列号:单台机器每毫秒最多生成4096个不重复ID。
优势 :全局唯一、有序递增、高性能、无需依赖数据库;
支持类型:Long、String字符串两种主键类型。
(2)使用方式
局部注解(优先级高于全局配置):
java
@TableId(type = IdType.ASSIGN_ID)
private Long id;
全局配置(所有实体统一雪花ID):
yaml
mybatis-plus:
global-config:
db-config:
id-type: assign_id
(3)执行效果
调用userMapper.insert(user)时,无需手动设置id,MP底层自动生成雪花ID,插入后自动回填到实体:
java
User user = new User();
user.setName("李思思");
userMapper.insert(user);
System.out.println(user.getId()); // 自动输出雪花Long数字,如1782356912345678912
方式4:ASSIGN_UUID UUID字符串主键
适用场景 :主键需要字符串、不关心有序性的业务;
底层生成32位无横线UUID字符串,主键字段类型必须为String。
使用:
java
@TableId(type = IdType.ASSIGN_UUID)
private String id;
缺点:UUID无序,数据库索引效率低于雪花数字ID,不推荐高并发分页场景。
方式5:NONE 跟随全局配置
实体主键不指定type,自动读取yml中id-type全局配置;
如果全局未配置,默认等价于INPUT,需要手动赋值ID。
3. 局部注解 vs 全局配置 优先级
局部@TableId(type) > 全局yml配置
同一项目不同表需要不同主键策略时,用局部注解单独覆盖;统一规则直接全局配置即可。
五、Mapper层内置CRUD接口(插入操作完整详解)
BaseMapper封装了所有单表基础操作,泛型T为实体类,Wrapper为条件构造器。
1. 插入方法 insert()
方法定义:
java
// 插入一条记录,返回受影响行数
int insert(T entity);
使用示例:
java
@Test
public void testInsert() {
User user = new User();
user.setName("李思思");
user.setAge(18);
user.setEmail("379872721@qq.com");
int rows = userMapper.insert(user);
System.out.println("影响行数:" + rows);
System.out.println("自动生成主键ID:" + user.getId()); // ID自动回填
}
底层逻辑:根据主键策略自动生成id,只插入实体中不为null的字段,动态拼接insert SQL。
六、配置SQL日志(开发必备)
默认不会打印执行的SQL语句,添加配置后完整输出SQL、参数、返回行数,方便调试:
yaml
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
日志输出示例:
==> Preparing: INSERT INTO user (name,age,email,id) VALUES (?,?,?,?)
==> Parameters: 李思思(String),18(Integer),379872721@qq.com(String),1782356912345678912(Long)
<== Updates: 1
补充笔记总结
- MP核心优势:单表零XML开发,内置CRUD、分页、逻辑删除、乐观锁、分布式ID;
- 实体映射三要素:
@TableName绑定表、@TableId主键策略、@TableField字段映射; - ID生成优先级:局部注解 > 全局配置,分布式业务优先使用
ASSIGN_ID雪花算法; - 快速开发固定流程:建表→引依赖→配数据源→写实体→Mapper继承BaseMapper→直接调用CRUD;
- 开发环境务必开启SQL日志,快速定位SQL错误、慢查询。