MyBatis-Plus 全景对比 MyBatis:核心进步 + 实战语法速查表
一、核心定位与本质关系MyBatis-Plus简称 MP是基于 MyBatis 只做增强、不做修改的开源持久层增强框架完美兼容原生 MyBatis 所有语法、配置与特性无需废弃原有 MyBatis 代码即可无缝升级。二者核心区别原生 MyBatis轻量化 SQL 映射框架自由度极高所有 CRUD、条件拼接、分页、主键策略均需手动实现重复代码多、开发效率低。MyBatis-Plus保留 MyBatis 灵活特性的同时封装通用能力、标准化开发规范零 SQL 实现单表全量 CRUD解决原生框架冗余、不统一、需插件适配的痛点是 SpringBoot 项目主流标配。二、全景维度对比MP 相比 MyBatis 的核心进步从开发效率、功能能力、工程规范、性能安全性四大维度全方位拆解 MP 的迭代升级点覆盖日常开发所有场景。1. 基础 CRUD彻底消灭重复 XML/SQL对比维度原生 MyBatisMyBatis-PlusMP 核心进步单表 CRUD手动编写 Mapper 接口方法、XML SQL 语句增删改查全量手写Mapper 继承BaseMapper、Service 继承IService零代码拥有 20 通用 CRUD 方法省去 80% 单表基础代码杜绝重复编码失误参数映射手动传参、绑定字段易出现参数名写错、类型不匹配问题自动 ORM 映射驼峰字段自动匹配数据库下划线字段简化参数绑定降低映射报错概率主键生成无内置策略需手动编码或自定义配置主键自增、UUID 等规则内置雪花算法、自增、UUID、ASSIGN_ID 等主流主键策略注解一键配置统一主键规范适配分布式场景2. 条件查询告别硬编码 SQL实现链式优雅查询对比维度原生 MyBatisMyBatis-PlusMP 核心进步条件拼接XML 中写if标签动态拼接 SQL代码冗长、可读性差、易出错内置QueryWrapper、LambdaQueryWrapper链式条件构造器Java 代码拼接查询条件无需手写动态 SQL代码简洁易维护字段容错硬写字段名拼写错误仅运行时报错无编译校验Lambda 构造器通过实体属性引用编译期校验字段合法性提前规避字段拼写错误减少线上 BugSQL 注入手动拼接字符串易引发 SQL 注入风险所有条件构造器自动参数预编译内置防 SQL 注入机制提升代码安全性无需手动处理防注入3. 高级功能原生缺失的企业级能力对比维度原生 MyBatisMyBatis-PlusMP 核心进步分页功能无内置分页需手写 LIMIT、COUNT 语句或引入 PageHelper 第三方插件配置繁琐内置分页拦截器一行配置开启物理分页自动封装分页总数、页码、数据列表开箱即用分页逻辑标准化无需额外适配逻辑删除需手动修改 DELETE 语句为 UPDATE统一删除状态代码分散不统一TableLogic注解一键开启自动将物理删除转为逻辑删除查询自动过滤已删除数据全局统一软删除规范业务无侵入自动填充新增/修改时手动 set 创建时间、更新时间、创建人、更新人重复代码多通过MetaObjectHandler配置TableField(fill ...)注解自动填充通用字段解放重复赋值代码统一基础字段填充规则代码生成无内置生成器需依赖第三方工具格式不统一内置代码生成器一键生成 Entity、Mapper、Service、Controller、DTO 全套代码标准化项目代码结构大幅提升新项目搭建效率乐观锁需手动实现版本号比对、更新逻辑自定义拦截规则内置乐观锁插件Version注解一键开启自动实现版本控制极简实现并发更新控制适配高并发场景4. 工程与性能更适配企业级开发规范统一原生 MyBatis 开发自由度过高团队代码风格参差不齐MP 基于约定大于配置统一 CRUD、分页、删除、填充规范便于团队维护。性能无损MP 所有增强能力均基于编译期、拦截器实现无运行时性能损耗和原生 MyBatis 执行效率一致。兼容性极强不影响原生 MyBatis 自定义 SQL、多表关联、复杂查询复杂场景可继续手写 XML简单场景用 MP 通用方法兼顾效率与灵活性。监控友好支持 SQL 日志打印、性能分析插件可直观查看执行 SQL、耗时便于问题排查。三、MyBatis-Plus 高频语法速查表开发必备整理项目中95% 高频使用的 MP 语法、注解、CRUD 方法、条件构造器直接复制即用无需重复查文档。1. 核心实体注解速查注解作用场景使用示例TableName实体类与数据库表名不匹配时指定表名TableName(sys_user)TableId指定主键字段、主键生成策略TableId(type IdType.ASSIGN_ID)雪花算法TableField指定非主键字段、自动填充、字段忽略TableField(fill FieldFill.INSERT)新增填充TableLogic标识逻辑删除字段TableLogic private Integer deleted;Version乐观锁版本号字段Version private Integer version;TableField(exist false)标识非数据库字段临时字段TableField(exist false) private String tempName;2. BaseMapper 通用 CRUD 方法速查Mapper 接口继承BaseMapper实体类后直接使用无需实现。// 新增 int insert(T entity); // 根据ID删除 int deleteById(Serializable id); // 根据条件删除 int delete(Param(ew) WrapperT queryWrapper); // 根据ID修改 int updateById(T entity); // 根据条件修改 int update(T entity, Param(ew) WrapperT updateWrapper); // 根据ID查询 T selectById(Serializable id); // 根据条件查询单条 T selectOne(WrapperT queryWrapper); // 根据条件查询列表 ListT selectList(WrapperT queryWrapper); // 分页查询 PageT selectPage(PageT page, WrapperT queryWrapper); // 查询总记录数 Long selectCount(WrapperT queryWrapper);3. 链式条件构造器速查Lambda 优先无编译报错基础查询条件// 1. 等值、不等值、范围查询 LambdaQueryWrapperUser wrapper new LambdaQueryWrapper(); wrapper.eq(User::getUsername, 张三) // 等于 .ne(User::getStatus, 0) // 不等于 .gt(User::getAge, 18) // 大于 .lt(User::getAge, 60) // 小于 .ge(User::getCreateTime, startTime) // 大于等于 .le(User::getCreateTime, endTime); // 小于等于 // 2. 模糊查询 wrapper.like(User::getUsername, 张) // 包含 .likeLeft(User::getPhone, 138) // 左模糊 .likeRight(User::getPhone, 99) // 右模糊 // 3. 空值、包含查询 wrapper.isNull(User::getEmail) // 为空 .isNotNull(User::getNickName) // 不为空 .in(User::getStatus, 1,2) // 包含指定值 .notIn(User::getType, 3,4); // 不包含指定值 // 4. 排序、去重 wrapper.orderByAsc(User::getAge) // 升序 .orderByDesc(User::getCreateTime) // 降序 .distinct();条件更新无需全字段赋值LambdaUpdateWrapperUser updateWrapper new LambdaUpdateWrapper(); // 只更新指定字段根据条件批量修改 updateWrapper.eq(User::getDeptId, 100) .set(User::getStatus, 1) .set(User::getUpdateTime, LocalDateTime.now()); userMapper.update(null, updateWrapper);4. 分页语法速查最简配置使用第一步配置分页拦截器全局一次配置Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // 开启物理分页 interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; }第二步业务代码使用// 参数当前页、每页条数 PageUser page new Page(1, 10); // 分页查询自动封装总页数、总条数、数据列表 PageUser userPage userMapper.selectPage(page, wrapper);5. Service 层常用封装方法Service 继承ServiceImplUserMapper, User后使用比 Mapper 更适配业务层// 新增/修改 save(T entity) updateById(T entity) saveOrUpdate(T entity) // 存在则更新不存在则新增 // 批量操作 batchInsert(ListT list) batchUpdate(ListT list) // 查询 getById(id) list(Wrapper) page(Page, Wrapper)四、MP 开发避坑要点核心注意事项仅单表优先用 MP多表关联、复杂子查询、特殊 SQL 场景建议手写原生 XML SQL避免条件构造器过度嵌套导致可读性变差。Lambda 构造器杜绝硬写字段名优先使用LambdaQueryWrapper避免字符串字段名引发编译不校验问题。逻辑删除需全局配置开启逻辑删除后MP 会自动过滤已删除数据如需查询已删除数据需手动关闭过滤规则。分页必须配置拦截器未配置分页拦截器会导致分页失效仅查询全量数据不会自动分页。继承场景开启 super 校验实体类继承父类时字段填充、查询需保证父类字段可被 MP 扫描识别。五、最终选型总结1.纯 MyBatis 适用场景老旧项目维护、极复杂多表 SQL、对框架轻量化极致要求、无快速开发需求的传统项目。2.MyBatis-Plus 适用场景99% 新项目SpringBoot 新项目、CRUD 业务量大、追求开发效率、需要统一工程规范、分布式项目、需要逻辑删除、自动填充、分页等企业级能力的场景。MP 并非替代 MyBatis而是赋能增强兼顾原生灵活性与高效开发能力是目前 Java 后端持久层开发的最优解决方案。