{T}

MyBatis-Plus 快速入门与核心注解

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。本章介绍如何快速接入 MyBatis-Plus,以及核心注解的用法。

为什么选择 MyBatis-Plus

优势说明
无侵入只做增强不做改变,引入它不会对现有工程产生影响
强大的 CRUD内置通用 Mapper、Service,少量配置即可实现单表大部分 CRUD 操作
Lambda 表达式通过 Lambda 表达式方便编写各类查询条件,无需担心字段写错
插件丰富分页、逻辑删除、乐观锁、自动填充等开箱即用
图表渲染中…

项目接入(Spring Boot 3.x + JDK 17)

Maven 依赖

xml
<properties>
    <java.version>17</java.version>
    <mybatis-plus.version>3.5.12</mybatis-plus.version>
</properties>

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- MyBatis-Plus(注意:Spring Boot 3.x 使用 mybatis-plus-spring-boot3-starter) -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
        <version>${mybatis-plus.version}</version>
    </dependency>

    <!-- MySQL Driver -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
Spring Boot 版本对应
  • Spring Boot 2.x:使用 mybatis-plus-boot-starter
  • Spring Boot 3.x:使用 mybatis-plus-spring-boot3-starter(包命名空间已切换为 jakarta.*

引入 MyBatis-Plus 后不要再次引入 MyBatis,以避免版本冲突。

配置文件

yaml
server:
  port: 8080

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
    username: root
    password: root1234

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  # 开发环境打印 SQL
    map-underscore-to-camel-case: true                      # 驼峰命名转换
  global-config:
    db-config:
      id-type: assign_id         # 全局主键策略:雪花算法
      logic-delete-field: deleted  # 逻辑删除字段
      logic-delete-value: 1        # 逻辑已删除值
      logic-not-delete-value: 0    # 逻辑未删除值
  mapper-locations: classpath:mapper/*.xml
配置项说明
log-implSQL 日志输出实现(开发环境使用 StdOut,生产环境关闭)
map-underscore-to-camel-case开启驼峰命名转换(user_nameuserName
id-type全局主键策略(assign_id = 雪花算法)
logic-delete-field逻辑删除全局字段名

启动类

java
package com.xiaoye.mybatisplus;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.xiaoye.mybatisplus.mapper")
public class MybatisPlusDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusDemoApplication.class, args);
    }
}

数据库初始化

sql
CREATE DATABASE mybatis_plus DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

USE mybatis_plus;

CREATE TABLE user (
    id BIGINT NOT NULL COMMENT '主键ID',
    name VARCHAR(30) DEFAULT NULL COMMENT '姓名',
    age INT DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
    create_time DATETIME DEFAULT NULL COMMENT '创建时间',
    update_time DATETIME DEFAULT NULL COMMENT '更新时间',
    version INT DEFAULT 1 COMMENT '版本号(乐观锁)',
    deleted INT DEFAULT 0 COMMENT '逻辑删除标记(0未删除,1已删除)',
    PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

核心注解详解

MyBatis-Plus 通过注解将实体类与数据库表进行映射。

注解一览表

注解作用常用属性示例
@TableName指定表名valueautoResultMap@TableName("sys_user")
@TableId指定主键typevalue@TableId(type = IdType.ASSIGN_ID)
@TableField指定字段映射valuefillexist@TableField(fill = FieldFill.INSERT)
@TableLogic逻辑删除valuedelval@TableLogic
@Version乐观锁@Version

实体类完整示例

java
package com.xiaoye.mybatisplus.entity;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;

@Data
@TableName("user")
public class User implements Serializable {

    @TableId(type = IdType.ASSIGN_ID)   // 主键:雪花算法
    private Long id;

    private String name;                  // 自动映射 user_name → name(驼峰转换)

    private Integer age;

    private String email;

    @TableField(fill = FieldFill.INSERT)        // 创建时自动填充
    private LocalDateTime createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE)  // 创建和更新时自动填充
    private LocalDateTime updateTime;

    @Version                                    // 乐观锁版本号
    @TableField(fill = FieldFill.INSERT)        // 创建时自动填充初始值 1
    private Integer version;

    @TableLogic                                 // 逻辑删除标记
    @TableField(fill = FieldFill.INSERT)        // 创建时自动填充初始值 0
    private Integer deleted;
}
@TableField 高级用法
  • exist = false:表示该字段不存在于数据库表中(用于 DTO 中额外的计算字段)
  • select = false:查询时不返回该字段(如密码字段)
  • update = "%s+1":更新时使用表达式(如 UPDATE SET read_count = read_count + 1

Mapper 和 Service 层

Mapper 接口

java
package com.xiaoye.mybatisplus.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiaoye.mybatisplus.entity.User;

@Mapper
public interface UserMapper extends BaseMapper<User> {
    // 继承 BaseMapper 后,无需编写 XML 即可使用以下内置方法:
    // insert、deleteById、updateById、selectById、selectList、selectPage 等
}

Service 层

java
// Service 接口
public interface UserService extends IService<User> {
    // IService 提供批量操作、Lambda 查询等高级能力
}

// Service 实现
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService {
    // ServiceImpl 内置了 saveBatch、updateBatchById、removeBatchByIds 等批量方法
}

BaseMapper vs IService 对比

能力BaseMapperIService
单条 CRUD
批量操作× 需手动循环saveBatchupdateBatchById
Lambda 查询× 需构造 WrapperlambdaQuery()lambdaUpdate()
链式查询×query().eq(...).list()
分页查询√ 需手动page()

基础 CRUD 测试

java
@SpringBootTest
class MybatisPlusDemoApplicationTests {

    @Autowired
    private UserMapper userMapper;

    // 插入
    @Test
    void testInsert() {
        User user = new User();
        user.setName("张三");
        user.setAge(25);
        user.setEmail("zhangsan@example.com");

        int rows = userMapper.insert(user);
        System.out.println("影响行数:" + rows);
        System.out.println("自动生成的ID:" + user.getId());  // 雪花算法生成的 Long 型 ID
    }

    // 根据 ID 查询
    @Test
    void testSelectById() {
        User user = userMapper.selectById(1L);
        System.out.println(user);
    }

    // 查询所有
    @Test
    void testSelectAll() {
        List<User> users = userMapper.selectList(null);
        // 注意:逻辑删除的记录会被自动过滤
        // 生成的 SQL: SELECT ... FROM user WHERE deleted=0
        users.forEach(System.out::println);
    }

    // 根据 ID 更新
    @Test
    void testUpdateById() {
        User user = userMapper.selectById(1L);
        user.setName("李四");
        user.setAge(30);

        int rows = userMapper.updateById(user);
        System.out.println("影响行数:" + rows);
    }

    // 根据 ID 删除(逻辑删除)
    @Test
    void testDeleteById() {
        int rows = userMapper.deleteById(1L);
        // 逻辑删除:UPDATE user SET deleted=1 WHERE id=1 AND deleted=0
        System.out.println("影响行数:" + rows);
    }
}

主键策略

MyBatis-Plus 提供多种主键生成策略,通过 @TableId 注解的 type 属性指定。

策略对比

策略说明适用场景
ASSIGN_ID雪花算法生成 Long 型 ID(默认分布式系统、单机系统
ASSIGN_UUID生成 UUID(32位字符串,无中划线)需要字符串主键
AUTO数据库自增单机系统、数据库支持自增
INPUT用户手动输入自定义主键场景
NONE跟随全局配置使用全局配置

雪花算法原理

code
雪花算法结构(64位 Long):
┌─────────────────────────────────────────────────────────────┐
│ 1位 │      41位时间戳       │  10位机器ID  │   12位序列号   │
│符号位│  (毫秒级时间戳)     │(5位数据中心+5位机器)│(毫秒内计数)│
└─────────────────────────────────────────────────────────────┘

特点

  • 全局唯一、趋势递增
  • 高性能(单机每秒可生成 400 万个 ID)
  • 不依赖数据库
  • 41 位时间戳可使用约 69 年
雪花算法注意事项
  1. ASSIGN_ID 策略要求实体类主键类型为 LongString
  2. 雪花算法依赖机器时钟,时钟回拨会导致 ID 重复
  3. 优先级:局部注解 > 全局配置 > 默认策略

使用示例

java
// 雪花算法(Long 型 ID)
@TableId(type = IdType.ASSIGN_ID)
private Long id;

// UUID(String 型 ID)
@TableId(type = IdType.ASSIGN_UUID)
private String id;

// 数据库自增
@TableId(type = IdType.AUTO)
private Long id;

全局配置

yaml
mybatis-plus:
  global-config:
    db-config:
      id-type: assign_id  # 全局默认使用雪花算法

下一步

掌握了基础接入和核心注解后,接下来学习:

版本差异(旧版 3.5.5 → 3.5.x)

特性旧版(3.5.5 时期)当前 3.5.x(如 3.5.12)
Boot 3 依赖坐标mybatis-plus-spring-boot3-starter不变,Boot 3 必须使用 boot3-starter
JDK 21 支持以 JDK 17 为目标3.5.6+ 完整支持 JDK 21(record、虚拟线程)
虚拟线程无特殊处理3.5.9+ 优化虚拟线程环境兼容(配合 Boot 3.2+ spring.threads.virtual.enabled)
主键策略IdType.ASSIGN_ID 雪花算法不变,仍为默认推荐
核心注解@TableName/@TableId/@TableField用法不变,无破坏性变更

本文示例基于 JDK 17 + Spring Boot 3.x 编写,依赖坐标已按 3.5.x 最新维护版本对齐;升级到 JDK 21 时无需修改任何注解或配置。