MyBatis-Plus简称 MP作为 MyBatis 的增强工具凭借 “只做增强不做改变” 的特性大幅简化了数据库操作开发流程是 Java 后端面试中的高频考点。本文整理了 MP 核心面试题并结合实战场景给出详细解答帮助大家吃透 MP 核心知识点。一、基础概念类1. 什么是 MyBatis-Plus它的核心优势是什么答MyBatis-Plus 是基于 MyBatis 的增强工具在 MyBatis 基础上仅做增强不做改变旨在简化开发、提高效率。核心优势无侵入引入后不影响现有 MyBatis 工程逻辑强大的 CRUD 封装内置通用 Mapper/Service无需手动编写单表 CRUD SQL灵活的条件构造器支持 Lambda 表达式编写查询条件避免字段写错主键自动生成支持 4 种以上主键策略含雪花算法内置功能丰富分页插件、性能分析插件、全局拦截插件、逻辑删除、乐观锁等代码生成器快速生成 Mapper/Model/Service/Controller 层代码。2. MyBatis-Plus 支持哪些数据库答支持所有兼容 MyBatis 且遵循标准 SQL 的数据库常见的有 MySQL、Oracle、DB2、PostgreSQL、SQLServer 等也适配国产数据库达梦、人大金仓、神通等。3. MyBatis-Plus 和 MyBatis 的区别是什么特性MyBatisMyBatis-Plus单表 CRUD需手动编写 SQL/XML内置通用 Mapper无需手动编写条件查询手动拼接 SQL条件构造器WrapperLambda 表达式分页需手动配置分页插件内置分页插件支持多数据库主键生成手动处理多种主键策略自增、雪花算法、UUID 等逻辑删除 / 乐观锁需手动实现注解 配置即可实现二、核心功能类4. MyBatis-Plus 的主键生成策略有哪些分别适用于什么场景答MP 通过TableId(type IdType.XXX)指定主键策略核心策略及场景AUTO数据库自增适用于单库、主键自增的场景INPUT手动输入主键适用于需自定义主键的场景ASSIGN_ID雪花算法生成分布式唯一 IDLong/String 类型适用于分布式系统ASSIGN_UUID生成 32 位 UUID适用于主键为字符串且需全局唯一的场景NONE未设置跟随全局配置。扩展雪花算法核心逻辑 ——41 位毫秒数 10 位机器 ID5 位数据中心 5 位机器12 位毫秒内流水号保证分布式环境下 ID 唯一且趋势递增。5. 如何实现 MyBatis-Plus 的分页功能答实现步骤配置分页拦截器3.4.0 版本Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // 指定数据库类型如MySQL interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }代码中使用 Page 对象分页Test public void testPage() { // 第2页每页3条数据 PageUser page new Page(2, 3); // 分页查询条件为null表示无过滤 PageUser userPage userMapper.selectPage(page, null); // 获取分页结果 ListUser records userPage.getRecords(); // 分页数据 long total userPage.getTotal(); // 总条数 long pages userPage.getPages(); // 总页数 }6. 什么是逻辑删除MyBatis-Plus 如何实现逻辑删除答逻辑删除并非物理删除数据库数据而是通过字段标记数据状态如deleted0未删除、deleted1已删除避免数据丢失。MP 实现逻辑删除步骤数据库表添加逻辑删除字段如deleted INT DEFAULT 0实体类字段添加TableLogic注解TableLogic private Integer deleted;配置文件指定逻辑删除值mybatis-plus: global-config: db-config: logic-delete-value: 1 # 已删除值 logic-not-delete-value: 0 # 未删除值原理执行delete操作时MP 自动转换为update如DELETE FROM user WHERE id1→UPDATE user SET deleted1 WHERE id1 AND deleted0查询时自动追加deleted0条件。7. MyBatis-Plus 的乐观锁实现原理是什么如何配置答乐观锁核心思想假设数据不会被并发修改仅在更新时检查版本号若版本号一致则更新否则更新失败解决并发修改冲突。MP 实现乐观锁步骤数据库表添加版本号字段如version INT DEFAULT 0实体类字段添加Version注解Version private Integer version;配置乐观锁拦截器Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // 乐观锁拦截器 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 分页拦截器若需分页可同时配置 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; }原理更新时自动拼接版本号条件且版本号自增如UPDATE product SET price1500, versionversion1 WHERE id1 AND version0。8. MyBatis-Plus 的条件构造器Wrapper有哪些常用用法答Wrapper 是 MP 的条件构造器核心常用实现类QueryWrapper查询、UpdateWrapper更新、LambdaQueryWrapperLambda 风格。常用 API 及场景// 1. 基础条件姓名非空、邮箱非空、年龄≥12 QueryWrapperUser wrapper new QueryWrapper(); wrapper.isNotNull(name) .isNotNull(email) .ge(age, 12); ListUser list userMapper.selectList(wrapper); // 2. 等值查询姓名李四 wrapper.eq(name, 李四); User user userMapper.selectOne(wrapper); // 3. 范围查询年龄20~30 wrapper.between(age, 20, 30); Integer count userMapper.selectCount(wrapper); // 4. 模糊查询姓名不含e、邮箱以t开头 wrapper.notLike(name, e) .likeRight(email, t); // 5. 排序子查询id倒序、id≥2 wrapper.orderByDesc(id) .inSql(id, select id from user where id2); // Lambda风格避免字段写错 LambdaQueryWrapperUser lambdaWrapper new LambdaQueryWrapper(); lambdaWrapper.eq(User::getName, 李四) .ge(User::getAge, 18);9. MyBatis-Plus 如何实现自定义 SQL答MP 支持保留 MyBatis 的自定义 SQL 能力步骤配置文件指定 Mapper XML 路径mybatis-plus: mapper-locations: classpath:mapper/*.xml # XML文件路径 type-aliases-package: com.mp.entity # 实体类别名包Mapper 接口定义自定义方法Mapper public interface UserMapper extends BaseMapperUser { // 自定义方法 ListUser selectByAge(Integer age); }编写 XML 文件如UserMapper.xmlxml?xml version1.0 encodingUTF-8? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.mp.mapper.UserMapper select idselectByAge resultTypeUser parameterTypeint SELECT * FROM user WHERE age #{age} /select /mapper调用自定义方法ListUser list userMapper.selectByAge(18);三、进阶应用类10. MyBatis-Plus 的逻辑删除和物理删除的区别实际项目中如何选择答物理删除直接删除数据库数据不可恢复适用于无保留价值的数据如测试数据、临时数据逻辑删除仅标记删除状态数据仍保留在库中适用于需保留数据痕迹的场景如用户、订单、商品等核心数据。选型建议核心业务数据订单、用户、交易记录用逻辑删除非核心临时数据用物理删除。11. MyBatis-Plus 的乐观锁和悲观锁的区别分别适用于什么场景特性乐观锁悲观锁核心思想假设不会并发冲突更新时校验假设会并发冲突操作前加锁实现方式版本号MP 注解 拦截器数据库锁如 FOR UPDATE性能无锁性能高加锁性能较低适用场景读多写少、并发冲突少写多读少、并发冲突多示例场景乐观锁商品库存读多写少偶尔并发悲观锁金融交易写多需严格保证数据一致性。12. MyBatis-Plus 如何配置日志为什么要配置日志答配置日志可查看 MP 自动生成的 SQL 语句便于调试和优化配置方式以控制台输出为例mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl日志输出内容包含执行的 SQL、参数、执行时间、结果集可快速定位 SQL 拼接或条件查询的问题。四、注解类13. MyBatis-Plus 常用注解有哪些分别作用是什么注解作用使用位置TableName指定实体类对应的数据表名实体类上TableId标记主键字段指定主键策略实体类主键字段上TableField标记非主键字段字段名映射、是否为数据库字段等实体类非主键字段上TableLogic标记逻辑删除字段实体类逻辑删除字段上Version标记乐观锁版本号字段实体类版本号字段上EnumValue标记枚举类映射数据库的字段枚举类字段上示例TableName(sys_user) // 表名映射 public class User { TableId(type IdType.ASSIGN_ID) // 雪花算法主键 private Long id; TableField(value user_name) // 字段名映射实体name → 表user_name private String name; TableLogic // 逻辑删除 private Integer deleted; Version // 乐观锁 private Integer version; }五、实战场景类14. 实际项目中如何解决 MyBatis-Plus 实体类与数据库表字段名不一致的问题答有 3 种解决方案注解映射通过TableName指定表名TableField(value 字段名)指定列名全局配置字段前缀若表字段统一带前缀如sys_可配置全局前缀mybatis-plus: global-config: db-config: table-prefix: sys_ # 表前缀开启下划线转驼峰默认开启MP 自动将数据库下划线字段如user_name映射为实体驼峰字段userName。15. MyBatis-Plus 的分页插件为什么查询总条数为 0如何排查答常见原因及排查步骤未配置分页拦截器检查MybatisPlusInterceptor是否注入且指定了正确的数据库类型分页对象使用错误需使用 MP 的Page对象而非自定义分页类数据库权限问题确认用户有查询COUNT(*)的权限条件构造器过滤了所有数据检查 Wrapper 条件是否正确多表联查自定义 SQL 分页需手动处理总条数selectPage仅支持单表多表需用selectMapsPage或手动拼接 COUNT SQL。