MyBatis-Plus vs MyBatis全面对比与选型指南前言MyBatis 是 Java 持久层框架中“灵活派”的代表而 MyBatis-Plus简称 MP在 MyBatis 的基础上做了增强号称“为简化而生”。很多初学者甚至资深开发者在选型时都会纠结到底用原生 MyBatis 还是 MyBatis-Plus本文将从一个客观、实战的角度全方位对比两者的区别包括核心功能、开发效率、SQL 控制、扩展机制以及适用场景并配以流程图和代码示例帮助你做出合理的技术决策。一、一句话定义框架定义MyBatis一款优秀的持久层框架支持定制化 SQL、存储过程以及高级映射避免了几乎所有的 JDBC 代码和手动设置参数。MyBatis-PlusMyBatis 的增强工具在 MyBatis 的基础上只做增强不做改变旨在简化开发、提高效率无侵入地提供通用 CRUD、代码生成器、条件构造器等特性。官方标语“为简化而生”二、核心区别概览保留原生能力原始JDBCMyBatisMyBatis-Plus增强功能通用Mapper条件构造器分页插件代码生成器等区别速览表对比维度MyBatisMyBatis-Plus设计理念灵活SQL 与代码分离简化开发提高效率约定大于配置单表 CRUD需要手写 SQL 或使用注解内置通用 Mapper无需写 SQL条件构造器无需要手动拼接 SQL 或使用第三方提供QueryWrapper/LambdaQueryWrapper分页实现手动写方言 SQL 或用 PageHelper内置分页插件自动生成 count 和分页 SQL代码生成器无官方支持可使用 MyBatis Generator内置强大代码生成器一键生成 Entity、Mapper、Service、Controller主键策略手动配置或使用selectKey支持多种主键策略雪花 ID、自增、UUID 等逻辑删除需要手动拦截器或自定义 SQL内置逻辑删除插件TableLogic注解自动填充无需手动设置 createTime/updateTime内置自动填充功能 (MetaObjectHandler)性能损耗几乎无微乎其微增强功能仅在编译/启动时生成代码学习曲线较陡需要掌握 XML 配置、动态 SQL平缓简单 CRUD 零 SQL适用场景复杂查询、需要精细控制 SQL、遗留系统快速开发、单表操作多、团队效率优先三、核心功能详细对比3.1 单表 CRUD 操作MyBatis 方式需要编写 Mapper 接口 XML 映射文件或注解手写 SQL。!-- UserMapper.xml --selectidselectByIdresultTypecom.example.UserSELECT * FROM user WHERE id #{id}/selectMyBatis-Plus 方式继承BaseMapperT直接调用内置方法。publicinterfaceUserMapperextendsBaseMapperUser{// 无需任何代码继承即可获得 insert, deleteById, updateById, selectList 等方法}// 使用UseruseruserMapper.selectById(1L);ListUserlistuserMapper.selectList(newQueryWrapperUser().eq(age,18));3.2 条件构造器Wrapper这是 MyBatis-Plus 最亮眼的功能之一极大简化了动态查询。// 查询 name 张三 且 age 20 的用户QueryWrapperUserwrappernewQueryWrapper();wrapper.eq(name,张三).gt(age,20);ListUserusersuserMapper.selectList(wrapper);// Lambda 方式避免字段名硬编码LambdaQueryWrapperUserlambdaWrappernewLambdaQueryWrapper();lambdaWrapper.eq(User::getName,张三).gt(User::getAge,20);而在原生 MyBatis 中你需要手动编写if标签或使用第三方条件构造器。3.3 分页实现MyBatis通常结合 PageHelper 分页插件或手动写 limit 子句。PageHelper.startPage(1,10);ListUserlistuserMapper.selectByCondition(...);PageInfoUserpageInfonewPageInfo(list);MyBatis-Plus内置分页插件API 更统一。// 配置分页插件Spring Boot 自动配置BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptorinterceptornewMybatisPlusInterceptor();interceptor.addInnerInterceptor(newPaginationInnerInterceptor(DbType.MYSQL));returninterceptor;}// 使用PageUserpagenewPage(1,10);LambdaQueryWrapperUserwrappernewLambdaQueryWrapper();wrapper.eq(User::getStatus,1);PageUserresultuserMapper.selectPage(page,wrapper);System.out.println(result.getRecords());// 数据列表System.out.println(result.getTotal());// 总记录数3.4 代码生成器MyBatis-Plus 官方提供强大的代码生成器可一键生成 Entity、Mapper、Service、Controller 等大幅提升开发效率。// 示例AutoGenerator 配置AutoGeneratorgeneratornewAutoGenerator();// 设置数据源、包名、策略等generator.execute();MyBatis 官方没有类似的生成器但可以使用第三方的 MyBatis Generator (MBG)不过配置相对繁琐。3.5 逻辑删除MyBatis需要手动拦截 SQL 或每次写 SQL 时加上deleted0条件。MyBatis-Plus在实体类字段上加TableLogic然后内置删除方法会自动变为更新逻辑删除字段查询时自动过滤已删除数据。TableLogicprivateIntegerdeleted;3.6 自动填充如 create_time, update_timeMyBatis-Plus 提供了MetaObjectHandler可以自动填充字段无需每次手动设置。ComponentpublicclassMyMetaObjectHandlerimplementsMetaObjectHandler{OverridepublicvoidinsertFill(MetaObjectmetaObject){this.strictInsertFill(metaObject,createTime,LocalDateTime.class,LocalDateTime.now());this.strictInsertFill(metaObject,updateTime,LocalDateTime.class,LocalDateTime.now());}OverridepublicvoidupdateFill(MetaObjectmetaObject){this.strictUpdateFill(metaObject,updateTime,LocalDateTime.class,LocalDateTime.now());}}四、工作流程对比MyBatis 执行流程调用 Mapper 接口方法MyBatis 动态代理解析 XML 或注解中的 SQL参数映射执行 SQL结果映射为实体对象返回结果MyBatis-Plus 执行流程增强部分通用 CRUD条件查询分页调用 BaseMapper 方法MP 拦截器方法类型判断自动生成 SQL解析 QueryWrapper分页插件改写 SQL交给 MyBatis 执行返回结果MP 并不会替换 MyBatis 的核心执行机制而是在其基础上注入自定义 SQL 片段通过 SQL 注入器和拦截器链实现增强。五、优缺点分析MyBatis优点缺点✅ SQL 与代码分离精细化控制❌ 单表操作仍需编写重复 SQL✅ 动态 SQL 强大if, choose, foreach❌ 无自带分页、逻辑删除等通用功能✅ 性能可控没有额外开销❌ 代码量较大开发效率相对低✅ 适合复杂查询、多表联查❌ 需要维护 XML 和接口映射MyBatis-Plus优点缺点✅单表 CRUD 零 SQL开发效率高❌ 多表复杂查询依然需要手写 SQL但可混合使用✅ 内置分页、条件构造器、逻辑删除、自动填充❌ 过度依赖 MP 特有 API 可能降低代码可移植性✅ 代码生成器一键生成基础代码❌ 如果滥用 Wrapper 会导致业务逻辑泄露到数据层✅ 无侵入可与 MyBatis 共存❌ 对动态表名、多租户等高级场景需要额外配置✅ 社区活跃文档丰富六、使用场景与选型建议场景推荐框架理由快速开发中小型项目单体/微服务MyBatis-Plus单表操作多通用功能节省大量时间大型复杂企业系统有资深 SQL 优化人员MyBatis 或MyBatis MP 混合复杂查询需要精细控制 SQLMP 仅用于单表遗留系统改造不想大量重写只引入 MP 作为辅助MP 无侵入可以逐步替换单表操作团队对 MyBatis 非常熟悉且已有成熟封装MyBatis避免引入额外依赖保持技术栈统一需要极高性能对 SQL 执行计划有极致要求MyBatisMP 的自动生成 SQL 可能不是最优可手动改写学习/教学/个人项目MyBatis-Plus快速出活体验现代开发方式最佳实践MyBatis-Plus MyBatis 混合使用。单表操作用 MP复杂多表查询、存储过程依然写在 XML 中互不干扰。七、代码示例同一个功能两种实现假设实现根据用户名和年龄区间查询用户列表并分页展示MyBatis 实现!-- UserMapper.xml --selectidselectByConditionresultTypeUserSELECT * FROM userwhereiftestname ! null and name ! AND name #{name}/ififtestminAge ! nullAND age #{minAge}/ififtestmaxAge ! nullAND age #{maxAge}/if/where/select// 配合 PageHelperPageHelper.startPage(pageNum,pageSize);ListUserlistuserMapper.selectByCondition(name,minAge,maxAge);PageInfoUserpageInfonewPageInfo(list);MyBatis-Plus 实现// 无需修改 XML直接使用 MPPageUserpagenewPage(pageNum,pageSize);LambdaQueryWrapperUserwrappernewLambdaQueryWrapper();wrapper.eq(StringUtils.hasText(name),User::getName,name).ge(minAge!null,User::getAge,minAge).le(maxAge!null,User::getAge,maxAge);PageUserresultuserMapper.selectPage(page,wrapper);可见 MP 代码量显著减少且可读性更高。八、总结MyBatis-Plus 不是 MyBatis 的替代品而是增强工具。它完全兼容 MyBatis你可以随时切换回原生方式。对于单表操作MP 可以极大提升效率对于复杂查询依然推荐手写 SQL 以获得最佳性能和控制力。选型时建议中小型项目直接用 MyBatis-Plus大型项目以 MyBatis 为主引入 MP 仅用于通用 CRUD。从长远维护角度看MP 遵循“约定大于配置”降低了团队沟通成本是当前 Java 后端开发的主流选择之一。官方文档MyBatis-Plus 官网
MyBatis-Plus vs MyBatis:全面对比与选型指南
发布时间:2026/6/3 10:19:14
MyBatis-Plus vs MyBatis全面对比与选型指南前言MyBatis 是 Java 持久层框架中“灵活派”的代表而 MyBatis-Plus简称 MP在 MyBatis 的基础上做了增强号称“为简化而生”。很多初学者甚至资深开发者在选型时都会纠结到底用原生 MyBatis 还是 MyBatis-Plus本文将从一个客观、实战的角度全方位对比两者的区别包括核心功能、开发效率、SQL 控制、扩展机制以及适用场景并配以流程图和代码示例帮助你做出合理的技术决策。一、一句话定义框架定义MyBatis一款优秀的持久层框架支持定制化 SQL、存储过程以及高级映射避免了几乎所有的 JDBC 代码和手动设置参数。MyBatis-PlusMyBatis 的增强工具在 MyBatis 的基础上只做增强不做改变旨在简化开发、提高效率无侵入地提供通用 CRUD、代码生成器、条件构造器等特性。官方标语“为简化而生”二、核心区别概览保留原生能力原始JDBCMyBatisMyBatis-Plus增强功能通用Mapper条件构造器分页插件代码生成器等区别速览表对比维度MyBatisMyBatis-Plus设计理念灵活SQL 与代码分离简化开发提高效率约定大于配置单表 CRUD需要手写 SQL 或使用注解内置通用 Mapper无需写 SQL条件构造器无需要手动拼接 SQL 或使用第三方提供QueryWrapper/LambdaQueryWrapper分页实现手动写方言 SQL 或用 PageHelper内置分页插件自动生成 count 和分页 SQL代码生成器无官方支持可使用 MyBatis Generator内置强大代码生成器一键生成 Entity、Mapper、Service、Controller主键策略手动配置或使用selectKey支持多种主键策略雪花 ID、自增、UUID 等逻辑删除需要手动拦截器或自定义 SQL内置逻辑删除插件TableLogic注解自动填充无需手动设置 createTime/updateTime内置自动填充功能 (MetaObjectHandler)性能损耗几乎无微乎其微增强功能仅在编译/启动时生成代码学习曲线较陡需要掌握 XML 配置、动态 SQL平缓简单 CRUD 零 SQL适用场景复杂查询、需要精细控制 SQL、遗留系统快速开发、单表操作多、团队效率优先三、核心功能详细对比3.1 单表 CRUD 操作MyBatis 方式需要编写 Mapper 接口 XML 映射文件或注解手写 SQL。!-- UserMapper.xml --selectidselectByIdresultTypecom.example.UserSELECT * FROM user WHERE id #{id}/selectMyBatis-Plus 方式继承BaseMapperT直接调用内置方法。publicinterfaceUserMapperextendsBaseMapperUser{// 无需任何代码继承即可获得 insert, deleteById, updateById, selectList 等方法}// 使用UseruseruserMapper.selectById(1L);ListUserlistuserMapper.selectList(newQueryWrapperUser().eq(age,18));3.2 条件构造器Wrapper这是 MyBatis-Plus 最亮眼的功能之一极大简化了动态查询。// 查询 name 张三 且 age 20 的用户QueryWrapperUserwrappernewQueryWrapper();wrapper.eq(name,张三).gt(age,20);ListUserusersuserMapper.selectList(wrapper);// Lambda 方式避免字段名硬编码LambdaQueryWrapperUserlambdaWrappernewLambdaQueryWrapper();lambdaWrapper.eq(User::getName,张三).gt(User::getAge,20);而在原生 MyBatis 中你需要手动编写if标签或使用第三方条件构造器。3.3 分页实现MyBatis通常结合 PageHelper 分页插件或手动写 limit 子句。PageHelper.startPage(1,10);ListUserlistuserMapper.selectByCondition(...);PageInfoUserpageInfonewPageInfo(list);MyBatis-Plus内置分页插件API 更统一。// 配置分页插件Spring Boot 自动配置BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptorinterceptornewMybatisPlusInterceptor();interceptor.addInnerInterceptor(newPaginationInnerInterceptor(DbType.MYSQL));returninterceptor;}// 使用PageUserpagenewPage(1,10);LambdaQueryWrapperUserwrappernewLambdaQueryWrapper();wrapper.eq(User::getStatus,1);PageUserresultuserMapper.selectPage(page,wrapper);System.out.println(result.getRecords());// 数据列表System.out.println(result.getTotal());// 总记录数3.4 代码生成器MyBatis-Plus 官方提供强大的代码生成器可一键生成 Entity、Mapper、Service、Controller 等大幅提升开发效率。// 示例AutoGenerator 配置AutoGeneratorgeneratornewAutoGenerator();// 设置数据源、包名、策略等generator.execute();MyBatis 官方没有类似的生成器但可以使用第三方的 MyBatis Generator (MBG)不过配置相对繁琐。3.5 逻辑删除MyBatis需要手动拦截 SQL 或每次写 SQL 时加上deleted0条件。MyBatis-Plus在实体类字段上加TableLogic然后内置删除方法会自动变为更新逻辑删除字段查询时自动过滤已删除数据。TableLogicprivateIntegerdeleted;3.6 自动填充如 create_time, update_timeMyBatis-Plus 提供了MetaObjectHandler可以自动填充字段无需每次手动设置。ComponentpublicclassMyMetaObjectHandlerimplementsMetaObjectHandler{OverridepublicvoidinsertFill(MetaObjectmetaObject){this.strictInsertFill(metaObject,createTime,LocalDateTime.class,LocalDateTime.now());this.strictInsertFill(metaObject,updateTime,LocalDateTime.class,LocalDateTime.now());}OverridepublicvoidupdateFill(MetaObjectmetaObject){this.strictUpdateFill(metaObject,updateTime,LocalDateTime.class,LocalDateTime.now());}}四、工作流程对比MyBatis 执行流程调用 Mapper 接口方法MyBatis 动态代理解析 XML 或注解中的 SQL参数映射执行 SQL结果映射为实体对象返回结果MyBatis-Plus 执行流程增强部分通用 CRUD条件查询分页调用 BaseMapper 方法MP 拦截器方法类型判断自动生成 SQL解析 QueryWrapper分页插件改写 SQL交给 MyBatis 执行返回结果MP 并不会替换 MyBatis 的核心执行机制而是在其基础上注入自定义 SQL 片段通过 SQL 注入器和拦截器链实现增强。五、优缺点分析MyBatis优点缺点✅ SQL 与代码分离精细化控制❌ 单表操作仍需编写重复 SQL✅ 动态 SQL 强大if, choose, foreach❌ 无自带分页、逻辑删除等通用功能✅ 性能可控没有额外开销❌ 代码量较大开发效率相对低✅ 适合复杂查询、多表联查❌ 需要维护 XML 和接口映射MyBatis-Plus优点缺点✅单表 CRUD 零 SQL开发效率高❌ 多表复杂查询依然需要手写 SQL但可混合使用✅ 内置分页、条件构造器、逻辑删除、自动填充❌ 过度依赖 MP 特有 API 可能降低代码可移植性✅ 代码生成器一键生成基础代码❌ 如果滥用 Wrapper 会导致业务逻辑泄露到数据层✅ 无侵入可与 MyBatis 共存❌ 对动态表名、多租户等高级场景需要额外配置✅ 社区活跃文档丰富六、使用场景与选型建议场景推荐框架理由快速开发中小型项目单体/微服务MyBatis-Plus单表操作多通用功能节省大量时间大型复杂企业系统有资深 SQL 优化人员MyBatis 或MyBatis MP 混合复杂查询需要精细控制 SQLMP 仅用于单表遗留系统改造不想大量重写只引入 MP 作为辅助MP 无侵入可以逐步替换单表操作团队对 MyBatis 非常熟悉且已有成熟封装MyBatis避免引入额外依赖保持技术栈统一需要极高性能对 SQL 执行计划有极致要求MyBatisMP 的自动生成 SQL 可能不是最优可手动改写学习/教学/个人项目MyBatis-Plus快速出活体验现代开发方式最佳实践MyBatis-Plus MyBatis 混合使用。单表操作用 MP复杂多表查询、存储过程依然写在 XML 中互不干扰。七、代码示例同一个功能两种实现假设实现根据用户名和年龄区间查询用户列表并分页展示MyBatis 实现!-- UserMapper.xml --selectidselectByConditionresultTypeUserSELECT * FROM userwhereiftestname ! null and name ! AND name #{name}/ififtestminAge ! nullAND age #{minAge}/ififtestmaxAge ! nullAND age #{maxAge}/if/where/select// 配合 PageHelperPageHelper.startPage(pageNum,pageSize);ListUserlistuserMapper.selectByCondition(name,minAge,maxAge);PageInfoUserpageInfonewPageInfo(list);MyBatis-Plus 实现// 无需修改 XML直接使用 MPPageUserpagenewPage(pageNum,pageSize);LambdaQueryWrapperUserwrappernewLambdaQueryWrapper();wrapper.eq(StringUtils.hasText(name),User::getName,name).ge(minAge!null,User::getAge,minAge).le(maxAge!null,User::getAge,maxAge);PageUserresultuserMapper.selectPage(page,wrapper);可见 MP 代码量显著减少且可读性更高。八、总结MyBatis-Plus 不是 MyBatis 的替代品而是增强工具。它完全兼容 MyBatis你可以随时切换回原生方式。对于单表操作MP 可以极大提升效率对于复杂查询依然推荐手写 SQL 以获得最佳性能和控制力。选型时建议中小型项目直接用 MyBatis-Plus大型项目以 MyBatis 为主引入 MP 仅用于通用 CRUD。从长远维护角度看MP 遵循“约定大于配置”降低了团队沟通成本是当前 Java 后端开发的主流选择之一。官方文档MyBatis-Plus 官网