MyBatis-Plus 笔记一

MyBatis-Plus 笔记一

一、MyBatis-Plus 基础概述

1. 简介

MyBatis-Plus(简称MP)是国内苞米豆团队开发的MyBatis增强工具 ,核心宗旨:只做增强、不做修改 ,无缝兼容原有MyBatis项目,引入后不会破坏现有代码逻辑,主打简化单表CRUD开发、提升开发效率。

官网地址:https://baomidou.com/

核心定位:MyBatis最佳搭档,像双人搭档一样大幅减少重复代码。

2. 核心五大特性

  1. 无侵入:纯增强,原有MyBatis代码完全不用改动,平滑接入;
  2. 损耗极小:项目启动自动注入基础CRUD,无额外性能开销,直接面向实体对象操作;
  3. 内置强大CRUD:通用Mapper、通用Service开箱即用,搭配条件构造器覆盖绝大多数单表查询场景;
  4. Lambda表达式支持:通过Lambda写查询条件,彻底杜绝手写数据库字段名写错的bug;
  5. 丰富配套功能:主键自动生成、代码生成器、物理分页、性能分析、全局拦截、逻辑删除、乐观锁一站式支持。

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)底层自动执行流程
  1. 扫描实体类:项目启动时自动扫描所有实体POJO;
  2. 反射解析:通过反射读取实体类名、属性名,映射数据库表名、字段名;
  3. 自动生成SQL:动态拼接insert/update/delete/select基础SQL;
  4. 注入MyBatis容器:把生成好的SQL语句注册到MyBatis,无需手动写XML。

二、SpringBoot快速上手Demo

前置准备

  1. 安装Java环境、IDEA,熟悉SpringBoot、Maven基础;
  2. 创建测试数据库与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扫描

两种二选一:

  1. 启动类加@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);
    }
}
  1. 每个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 数据库自增主键

适用场景 :单体项目、单库,无分布式场景;

实现步骤

  1. 数据库主键id字段设置auto_increment自增约束;
  2. 实体主键注解指定类型:
java 复制代码
@TableId(type = IdType.AUTO)
private Long id;

执行逻辑 :插入数据时,数据库自动生成自增id,插入完成后自动回填到实体对象中;

缺点:分库分表、分布式多节点环境下会出现ID重复,不适合微服务。

方式2:INPUT 手动输入主键

适用场景 :自定义主键、Redis预生成全局ID、外部系统传入主键;

实现步骤

  1. 注解配置:
java 复制代码
@TableId(type = IdType.INPUT)
private Long id;
  1. 插入数据前必须手动给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. 1位符号位:固定0,保证正数;
  2. 41位时间戳:毫秒级,可使用69年;
  3. 10位机器ID:5位数据中心ID + 5位机器节点ID,最多支持1024台服务;
  4. 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

补充笔记总结

  1. MP核心优势:单表零XML开发,内置CRUD、分页、逻辑删除、乐观锁、分布式ID;
  2. 实体映射三要素:@TableName绑定表、@TableId主键策略、@TableField字段映射;
  3. ID生成优先级:局部注解 > 全局配置,分布式业务优先使用ASSIGN_ID雪花算法;
  4. 快速开发固定流程:建表→引依赖→配数据源→写实体→Mapper继承BaseMapper→直接调用CRUD;
  5. 开发环境务必开启SQL日志,快速定位SQL错误、慢查询。