MyBatis-Plus 核心知识点

一、MyBatis-Plus 基础认知

1. 什么是 MyBatis-Plus?

MyBatis-Plus(简称 MP)是 MyBatis 的增强工具,遵循 "只做增强不做改变" 的核心原则,在不侵入原有 MyBatis 逻辑的前提下,通过封装通用能力简化开发流程。

2. 核心优势

表格

优势点 具体说明
无侵入 引入后无需修改现有 MyBatis 代码,完全兼容 MyBatis 所有功能
高效 CRUD 内置 BaseMapper/IService,单表增删改查无需手写 SQL
灵活查询 Lambda 条件构造器避免字段硬编码错误,查询条件拼接更安全
便捷功能 内置主键生成(雪花算法)、分页、逻辑删除、乐观锁等常用功能
提效工具 代码生成器一键生成 Mapper/Model/Service/Controller 全套代码

3. 支持的数据库

MP 兼容所有支持 MyBatis 的标准 SQL 数据库,覆盖:

  • 主流数据库:MySQL、Oracle、DB2、PostgreSQL、SQLServer、SQLite 等;
  • 国产数据库:达梦、人大金仓、神通、瀚高、高斯等;
  • 核心前提:数据库需遵循标准 SQL 语法,且有适配 MyBatis 的底层驱动。

4. 与 MyBatis 的核心区别

表格

特性 MyBatis MyBatis-Plus
单表 CRUD 手动编写 SQL/XML 内置 BaseMapper,无需手写
条件查询 手动拼接 SQL Lambda 条件构造器(Wrapper),更安全
分页 需手动配置插件 + 编写分页 SQL 内置分页插件,Page 对象一键分页
主键生成 手动处理 多策略(自增、雪花算法、UUID 等)
逻辑删除 / 乐观锁 手动实现 注解 + 配置即可开箱即用

二、核心功能与实现

1. 主键生成策略

MP 通过 @TableId 注解指定主键策略,适配不同业务场景:

策略类型 核心逻辑 适用场景
AUTO 数据库自增主键 单库、主键自增的简单场景
INPUT 手动输入主键值 需自定义主键(如业务编码)
ASSIGN_ID 雪花算法生成分布式唯一 ID 分布式系统、主键为 Long/String 类型
ASSIGN_UUID 生成 32 位无横线 UUID 字符串主键、需全局唯一的场景
NONE 未指定,跟随全局配置 继承项目全局主键策略

扩展:雪花算法 = 41 位时间戳 + 10 位机器 ID + 12 位序列号,保证分布式 ID 唯一且趋势递增。

2. 分页功能实现

MP 分页需先配置拦截器,再通过 Page 对象实现,步骤如下:

步骤 1:配置分页拦截器(3.4.0+ 版本)
复制代码
@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 指定数据库类型,避免分页语法兼容问题
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}
步骤 2:代码中使用 Page 对象分页
复制代码
@Test
public void testPage() {
    // 参数:页码(从1开始)、每页条数
    Page<User> page = new Page<>(2, 3);
    // 分页查询(第二个参数为查询条件,null表示无条件)
    Page<User> resultPage = userMapper.selectPage(page, null);
    
    // 获取分页结果
    List<User> dataList = resultPage.getRecords(); // 当前页数据
    long total = resultPage.getTotal(); // 总条数
    long pages = resultPage.getPages(); // 总页数
    boolean hasNext = resultPage.hasNext(); // 是否有下一页
}

注意 :多表联查分页需使用 selectMapsPage,或手动拼接 COUNT SQL。

3. 逻辑删除

定义

逻辑删除是通过字段标记数据删除状态(而非物理删除),MP 自动将 DELETE 操作转为 UPDATE,查询时自动过滤已删除数据。

实现步骤
  1. 数据库:添加逻辑删除字段(如 deleted INT DEFAULT 0);

  2. 实体类:字段添加 @TableLogic 注解

    java

    运行

    复制代码
    public class User {
        @TableLogic // 标记逻辑删除字段
        private Integer deleted;
    }
  3. 配置文件:指定删除 / 未删除值 yaml

    复制代码
    mybatis-plus:
      global-config:
        db-config:
          logic-delete-value: 1 # 已删除
          logic-not-delete-value: 0 # 未删除
实现原理
  • 删除操作:DELETE FROM user WHERE id=1 → 自动转为 UPDATE user SET deleted=1 WHERE id=1 AND deleted=0
  • 查询操作:自动追加 AND deleted=0 条件,无需手动编写。

4. 乐观锁

核心思想

假设数据不会发生并发冲突,仅在更新时检查版本号,版本一致则更新(版本号 +1),否则更新失败。

实现步骤
  1. 数据库:添加版本号字段(如 version INT DEFAULT 0);

  2. 实体类:字段添加 @Version 注解

    复制代码
    public class Product {
        @Version // 标记乐观锁版本字段
        private Integer version;
    }
  3. 配置乐观锁拦截器

    复制代码
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 乐观锁拦截器
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        // 分页拦截器(可选)
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
实现原理

更新 SQL 自动拼接版本条件:UPDATE product SET price=1500, version=version+1 WHERE id=1 AND version=0

5. 条件构造器(Wrapper)

Wrapper 是 MP 条件构造核心,支持各类查询条件拼接,常用实现类及用法如下:

实现类 特点
QueryWrapper 普通条件构造(字段通过字符串指定)
LambdaQueryWrapper Lambda 风格(字段方法引用,推荐,避免字段硬编码)
UpdateWrapper 专用于更新操作的条件构造

常用 API 示例

复制代码
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getName, "李四")    // 等值查询
       .ge(User::getAge, 18)         // 大于等于
       .like(User::getEmail, "test") // 模糊查询
       .orderByDesc(User::getId);    // 降序排序

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

6. 自定义 SQL

MP 完全兼容 MyBatis 自定义 SQL 能力,实现步骤:

  1. 配置 XML 路径

    复制代码
    mybatis-plus:
      mapper-locations: classpath:mapper/*.xml # XML文件路径
      type-aliases-package: com.mp.entity # 实体别名包
  2. Mapper 接口定义自定义方法

    复制代码
    @Mapper
    public interface UserMapper extends BaseMapper<User> {
        // 自定义方法
        List<User> selectByAge(Integer age);
    }
  3. 编写 XML 映射文件(UserMapper.xml)

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.mp.mapper.UserMapper">
        <select id="selectByAge" resultType="User">
            SELECT * FROM user WHERE age = #{age}
        </select>
    </mapper>
  4. 调用:List<User> list = userMapper.selectByAge(18);

7. 日志配置

配置方式(控制台输出)
复制代码
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
日志作用
  • 查看 MP 自动生成的 SQL,验证条件构造是否正确;
  • 查看参数绑定结果,排查参数传递错误;
  • 查看 SQL 执行时间,定位慢 SQL;
  • 查看结果集,验证数据映射是否正确。

8. 常用注解

注解 作用 使用位置
@TableName 指定实体对应的数据库表名 实体类上
@TableId 标记主键,指定主键生成策略 主键字段上
@TableField 映射非主键字段(名称、是否为数据库字段) 非主键字段上
@TableLogic 标记逻辑删除字段 逻辑删除字段上
@Version 标记乐观锁版本号字段 版本号字段上
@EnumValue 标记枚举类映射数据库的字段 枚举类字段上

示例

复制代码
@TableName("sys_user") // 表名映射
public class User {
    @TableId(type = IdType.ASSIGN_ID) // 雪花算法主键
    private Long id;
    
    @TableField("user_name") // 字段名映射(name → user_name)
    private String name;
}

三、实战问题解决

1. 实体类与数据库表字段名不一致

解决方式按优先级排序:

  1. 推荐 :开启下划线转驼峰(MP 默认开启),自动将数据库下划线字段(user_name)映射为实体驼峰字段(userName);

  2. 注解映射:通过 @TableName 指定表名,@TableField(value = "字段名") 指定列名;

  3. 全局表前缀配置: yaml

    复制代码
    mybatis-plus:
      global-config:
        db-config:
          table-prefix: sys_ # 所有表统一前缀(如 sys_user)

2. 分页插件查询总条数为 0 的排查步骤

  1. 检查分页拦截器:确认 MybatisPlusInterceptor 已注入,且指定了正确的数据库类型;
  2. 检查分页对象:必须使用 MP 的 Page 对象,而非自定义分页类;
  3. 检查条件构造器:确认 Wrapper 条件未过滤所有数据(如误加 eq("id", 0));
  4. 检查数据库权限:确认用户有查询 COUNT(*) 的权限;
  5. 多表联查场景:selectPage 仅支持单表,多表需用 selectMapsPage 或手动拼接 COUNT SQL。

3. 逻辑删除 vs 物理删除

表格

类型 操作方式 数据恢复 适用场景
物理删除 DELETE 语句直接删除数据 不可恢复 测试数据、临时数据、无价值数据
逻辑删除 UPDATE 语句标记删除状态 可恢复 用户、订单、商品等核心业务数据

4. 乐观锁 vs 悲观锁

表格

特性 乐观锁 悲观锁
核心思想 假设无并发冲突,更新时校验版本号 假设必有冲突,操作前加锁
实现方式 MP 注解 + 版本号 数据库锁(如 SELECT ... FOR UPDATE
性能 无锁,性能高 加锁,性能较低
适用场景 读多写少(如商品库存) 写多读少(如金融交易)

四、核心要点总结

  1. MP 是 MyBatis 的增强工具,核心优势是 "无侵入 + 高效 CRUD + 丰富功能",完全兼容 MyBatis 原有特性;
  2. 核心功能落地:分页需配置拦截器 + Page 对象、逻辑删除靠注解 + 状态标记、乐观锁依赖版本号校验、条件构造优先用 Lambda 风格;
  3. 实战关键:字段映射优先用下划线转驼峰,核心数据用逻辑删除,分页总条数为 0 需排查拦截器 / 分页对象 / 多表联查。
相关推荐
码界奇点2 小时前
基于Spring MVC和MyBatis的妖气山视频管理系统设计与实现
java·spring·毕业设计·mvc·mybatis·源代码管理
indexsunny2 小时前
互联网大厂Java面试实战:从Spring Boot到微服务与Kafka的深度探讨
java·spring boot·junit·kafka·mybatis·hibernate·microservices
LSL666_3 小时前
5 MySQL驱动类选择与数据库连接 URL 时区配置
数据库·mysql·mybatis·mybatisplus
青槿吖15 小时前
【保姆级教程】Spring事务控制通关指南:XML+注解双版本,避坑指南全奉上
xml·java·开发语言·数据库·sql·spring·mybatis
小涛不学习15 小时前
Java 后端核心框架面试题(Spring / SpringMVC / MyBatis / MyBatis-Plus)
java·spring·mybatis
那我掉的头发算什么20 小时前
【博客系统】基于Spring全家桶的博客系统(下)
java·后端·spring·mybatis·开发
小王不爱笑13220 小时前
MyBatis-Plus 入门到实战,极简实现单表 CRUD
mybatis
dreamxian1 天前
苍穹外卖day07
java·spring boot·后端·spring·mybatis
mengqudoh1 天前
vue springboot mybatis实现自定义条件检索功能
vue.js·spring boot·mybatis