MyBatis-Plus核心功能与最佳实践详解
1. MyBatis-Plus核心定位与设计哲学MyBatis-Plus简称MP作为MyBatis的增强工具包其核心设计理念可以用八个字概括只做增强不做改变。这个理念贯穿了整个框架的设计与实现。在实际项目中使用MP时开发者无需对现有MyBatis项目做任何改动只需简单引入依赖即可获得强大的功能扩展。MP通过精妙的设计实现了与原生MyBatis的无缝兼容。其核心机制是在MyBatis原有组件基础上进行功能扩展而非替换。例如通过SqlInjector扩展SQL语句生成能力通过Interceptor链增强执行过程通过Wrapper体系构建条件查询这种设计带来的直接好处是零侵入性现有MyBatis项目可以平滑升级渐进式增强可按需使用MP提供的功能技术栈统一保持与MyBatis生态的一致性提示虽然MP声称不做改变但在实际使用中仍需注意其自动注入的SQL可能会影响某些特殊场景下的MyBatis行为这点我们会在后续章节详细讨论。2. 基础环境搭建与配置2.1 依赖引入与版本选择当前最新稳定版本为3.5.17截至2023年10月建议通过Maven或Gradle引入dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.17/version /dependency版本选择建议Spring Boot 2.x项目使用3.5.x系列Spring Boot 3.x项目需要3.5.3及以上版本非Spring项目使用核心包mybatis-plus而非starter2.2 基础配置项解析在application.yml中需要配置的基本项mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # SQL日志输出 map-underscore-to-camel-case: true # 自动驼峰转换 global-config: db-config: id-type: auto # 主键生成策略 logic-delete-field: deleted # 逻辑删除字段 logic-not-delete-value: 0 # 未删除值 logic-delete-value: 1 # 删除值关键配置说明log-impl开发阶段建议开启生产环境应关闭map-underscore-to-camel-case数据库字段命名风格转换id-type主键生成策略auto表示数据库自增3. 核心CRUD操作详解3.1 实体类与Mapper基础MP通过泛型机制实现通用CRUD操作。基础使用需要两个组件实体类使用注解标记表映射关系Mapper接口继承BaseMapper接口典型实体类示例Data TableName(sys_user) // 显式指定表名 public class User { TableId(type IdType.AUTO) // 主键策略 private Long id; TableField(username) // 字段映射 private String name; private Integer age; TableField(exist false) // 非表字段 private String tempField; }Mapper接口定义public interface UserMapper extends BaseMapperUser { // 可自定义扩展方法 ListUser selectByName(Param(name) String name); }3.2 条件构造器实战MP提供了强大的条件构造器Wrapper体系主要分为两类QueryWrapper查询条件构造UpdateWrapper更新条件构造复杂查询示例QueryWrapperUser wrapper new QueryWrapper(); wrapper.select(id, username, age) .like(username, 张) .between(age, 20, 30) .orderByDesc(create_time) .last(limit 10); ListUser users userMapper.selectList(wrapper);Lambda表达式写法推荐ListUser users userMapper.selectList(Wrappers.UserlambdaQuery() .select(User::getId, User::getName, User::getAge) .like(User::getName, 张) .between(User::getAge, 20, 30) .orderByDesc(User::getCreateTime) .last(limit 10));4. 高级特性深度解析4.1 分页查询实现原理MP的分页功能基于MyBatis的拦截器机制实现。使用前需要配置分页插件Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }分页查询示例PageUser page new Page(1, 10); // 当前页每页数量 QueryWrapperUser wrapper new QueryWrapper(); wrapper.eq(dept_id, 2); IPageUser result userMapper.selectPage(page, wrapper); System.out.println(总记录数 result.getTotal()); System.out.println(总页数 result.getPages()); result.getRecords().forEach(System.out::println);注意不同数据库的分页语法差异由DbType参数处理MP会自动适配MySQL、Oracle等数据库的分页语法。4.2 自动填充功能剖析MP的自动填充功能常用于处理创建时间、更新时间等通用字段。实现步骤在实体类字段上添加注解TableField(fill FieldFill.INSERT) private LocalDateTime createTime; TableField(fill FieldFill.INSERT_UPDATE) private LocalDateTime updateTime;实现MetaObjectHandler接口Component public class MyMetaObjectHandler implements MetaObjectHandler { Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, createTime, LocalDateTime.class, LocalDateTime.now()); } Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, updateTime, LocalDateTime.class, LocalDateTime.now()); } }5. 企业级应用实践5.1 多租户架构实现MP通过TenantLineInnerInterceptor实现多租户隔离。配置示例Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); // 多租户拦截器 TenantLineInnerInterceptor tenantInterceptor new TenantLineInnerInterceptor(); tenantInterceptor.setTenantLineHandler(new TenantLineHandler() { Override public String getTenantIdColumn() { return tenant_id; // 租户字段名 } Override public Expression getTenantId() { return new StringValue(T001); // 实际应从上下文中获取 } }); interceptor.addInnerInterceptor(tenantInterceptor); return interceptor; }5.2 性能优化建议批量操作优化ListUser userList new ArrayList(); // 添加数据... // 批量插入性能比循环单条插入高10倍以上 userService.saveBatch(userList, 1000); // 每批1000条SQL执行分析Bean public PerformanceInterceptor performanceInterceptor() { PerformanceInterceptor interceptor new PerformanceInterceptor(); interceptor.setMaxTime(1000); // 超过1秒的SQL记录警告 interceptor.setFormat(true); // 格式化SQL return interceptor; }逻辑删除优化 对于大表逻辑删除建议添加deleted字段的索引避免在逻辑删除字段上使用not null约束定期归档已删除数据6. 常见问题排查指南6.1 典型异常处理SQL注入警告WARN SqlExplainUtils - SQL injection warning解决方案检查Wrapper的last()方法调用避免直接拼接SQL片段分页失效 确保配置了分页拦截器使用IPage作为返回类型没有其他拦截器修改了SQL自动填充不生效 检查实体类字段注解是否正确MetaObjectHandler是否被Spring管理字段名称是否一致6.2 与Spring Boot 3.x的兼容性Spring Boot 3.x环境下需注意必须使用MP 3.5.3版本需要显式配置MapperScan注解部分依赖需要调整dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.17/version exclusions exclusion groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId /exclusion /exclusions /dependency dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version3.0.1/version /dependency7. 生态工具链整合7.1 MybatisX插件使用MybatisX是IDEA插件提供实体类与Mapper快速跳转XML与接口方法导航代码生成功能SQL自动补全安装方式IDEA插件市场搜索MybatisX支持功能AltEnter生成CRUD代码字段名自动提示结果集映射生成7.2 代码生成器配置MP提供的代码生成器可以快速生成Entity、Mapper、Service、Controller等层代码FastAutoGenerator.create(jdbc:mysql://localhost:3306/test, root, 123456) .globalConfig(builder - builder .author(baomidou) .outputDir(System.getProperty(user.dir) /src/main/java)) .packageConfig(builder - builder .parent(com.example.demo) .moduleName(system)) .strategyConfig(builder - builder .addInclude(sys_user, sys_role) // 包含的表 .entityBuilder() .enableLombok() .controllerBuilder() .enableRestStyle()) .execute();生成策略配置项enableLombok使用Lombok注解enableChainModel启用链式调用enableRestStyle生成RestControllerenableTableFieldAnnotation生成TableField注解8. 最佳实践与架构建议8.1 分层架构设计推荐的项目结构src/main/java ├── config # MP配置类 ├── controller # 表现层 ├── service # 业务层 │ ├── impl # 实现类 ├── mapper # 数据访问层 ├── entity # 实体类 ├── dto # 数据传输对象 ├── vo # 视图对象 └── util # 工具类各层职责划分Controller层参数校验结果包装异常处理Service层业务逻辑实现事务控制领域模型转换Mapper层数据库操作SQL定义简单条件查询8.2 复杂查询处理方案对于复杂查询场景推荐方案XML映射文件select idselectComplex resultTypecom.example.vo.UserVO SELECT u.*, d.dept_name FROM sys_user u LEFT JOIN sys_dept d ON u.dept_id d.id where if testparam.deptId ! null AND u.dept_id #{param.deptId} /if /where /selectQueryDSL集成public ListUser queryByDSL(UserQuery query) { JPAQueryFactory queryFactory new JPAQueryFactory(entityManager); QUser qUser QUser.user; return queryFactory.selectFrom(qUser) .where(qUser.age.gt(query.getMinAge()) .and(qUser.name.like(query.getKeyword() %))) .fetch(); }动态SQL构建public ListUser dynamicQuery(UserQuery query) { return lambdaQuery() .gt(query.getMinAge() ! null, User::getAge, query.getMinAge()) .like(StringUtils.isNotBlank(query.getKeyword()), User::getName, query.getKeyword() %) .list(); }在实际项目中我通常会根据查询复杂度选择合适的方式简单查询用Wrapper中等复杂度用XML特别复杂的考虑QueryDSL或原生SQL。这种分层策略既能保证开发效率又能应对各种复杂场景。

相关新闻

从GPT-2到Qwen3:12代LLM架构演进图谱(含287项指标对比+3个未公开技术断点)

从GPT-2到Qwen3:12代LLM架构演进图谱(含287项指标对比+3个未公开技术断点)

更多请点击: https://intelliparadigm.com 第一章:大语言模型LLM原理的范式革命与历史坐标 传统自然语言处理长期依赖规则系统与统计模型,从n-gram到隐马尔可夫模型(HMM),再到早期的循环神经网络&#xff…

2026/7/21 11:06:55阅读更多 →
Python+Appium实现微信自动化:从环境搭建到实战脚本编写

Python+Appium实现微信自动化:从环境搭建到实战脚本编写

1. 项目概述:为什么选择 Python Appium 来“操作”微信? 如果你正在看这篇文章,大概率是遇到了这样的场景:需要定时给某个群发消息、想自动处理微信里的文件、或者测试自家App与微信的交互流程。手动操作不仅枯燥,还容…

2026/7/21 11:07:00阅读更多 →
Golang实现JWT身份验证与安全实践指南

Golang实现JWT身份验证与安全实践指南

1. JWT基础与Golang实现概述JSON Web Token(JWT)已成为现代Web应用中身份验证和授权的标准方案。作为Go开发者,使用golang-jwt/jwt库可以快速实现安全的令牌机制。这个由社区维护的库支持RFC 7519标准,提供完整的JWT生成、签名和验…

2026/7/21 15:37:00阅读更多 →
揭秘开源大模型更新节奏真相:17个主流模型版本迭代周期对比,90%开发者忽略的维护风险预警

揭秘开源大模型更新节奏真相:17个主流模型版本迭代周期对比,90%开发者忽略的维护风险预警

更多请点击: https://kaifayun.com 第一章:开源大模型更新节奏真相全景概览 开源大模型的版本演进并非线性发布,而是由社区活跃度、算力资源、评测反馈与生态适配四重因素动态驱动。高频更新常集中于模型权重微调、量化方案迭代与推理框架兼…

2026/7/22 0:39:35阅读更多 →
Cargo 与容器构建:多阶段构建把镜像从 2GB 压缩到 50MB 的实操

Cargo 与容器构建:多阶段构建把镜像从 2GB 压缩到 50MB 的实操

Cargo 与容器构建:多阶段构建把镜像从 2GB 压缩到 50MB 的实操 一、2GB 镜像的成因 —— Rust 编译产物为什么这么大 很多人以为 Rust 编译出来的二进制应该很小,这其实是个误解。Debug 模式编译的 Rust 二进制确实可以很大,因为它包含了大量…

2026/7/22 0:37:33阅读更多 →
从git 一个分支cherry-pick apk 到另外一个分支!

从git 一个分支cherry-pick apk 到另外一个分支!

1.找到原分支的hash值 在原分支下面执行 git log --oneline b35b237c9f4 2.在新分支上执行 git cherry-pick b35b237c9f4 error: could not apply b35b237c9f4… 修复缺陷 hint: After resolving the conflicts, mark them with hint: “git add/rm ”, then run hint: “git c…

2026/7/22 0:37:33阅读更多 →
WebAssembly 在 Serverless 中的应用:冷启动 10ms 的 AI 推理函数

WebAssembly 在 Serverless 中的应用:冷启动 10ms 的 AI 推理函数

WebAssembly 在 Serverless 中的应用:冷启动 10ms 的 AI 推理函数 一、Serverless AI 推理的冷启动困境 Serverless 架构的一个核心承诺是"按需付费",但代价是冷启动延迟。当一个推理函数长时间没被调用后,云平台需要启动容器、加载…

2026/7/22 0:37:33阅读更多 →
颠覆传统菜谱软件只选择最高效简单的做法,编写程序,强制混搭不同菜系做法,自创菜品,锻炼跨界组合的创新逻辑。

颠覆传统菜谱软件只选择最高效简单的做法,编写程序,强制混搭不同菜系做法,自创菜品,锻炼跨界组合的创新逻辑。

一、实际应用场景描述(基于心理健康与创新能力视角)在心理健康与创新能力研究中,“跨界重组(Cross-domain Recombination)” 被认为是产生原创想法的重要机制之一。许多突破性创新(如 iPhone、分子料理、设…

2026/7/22 0:37:33阅读更多 →
颠覆传统提醒软件只催促不要拖延,编写程序主动设置合理拖延时限,在截止压力下激发大脑应急创新思维。

颠覆传统提醒软件只催促不要拖延,编写程序主动设置合理拖延时限,在截止压力下激发大脑应急创新思维。

一、实际应用场景描述(基于心理健康与创新能力视角)在心理健康与创新能力相关研究中,有一个被反复验证的观点:适度的截止压力(Deadline Pressure)有助于激发创造性思维,但过度压迫会损害心理健康…

2026/7/22 0:37:33阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/21 0:51:49阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 0:51:49阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 0:51:49阅读更多 →
中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业做小程序,最常见的矛盾是预算有限,但又不希望功能太单薄;没有技术团队,但又希望后续能自己运营;想快速上线,又担心隐性收费和售后失联。选型时如果只看“低价套餐”或“案例数量”,很容…

2026/7/22 0:01:17阅读更多 →
GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

企业做营销,最怕钱花完了,资产没有留下。 效果广告能带来一段时间的曝光,但预算停止后,流量往往也随之停止。短视频内容可能在几天内冲高,也可能很快沉下去。AI搜索时代,企业需要重新思考一个问题&#xff…

2026/7/22 0:01:17阅读更多 →
Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复 一、你的 Agent 在"再想想"的循环里绕了 12 轮,用户已经关窗口了 Agent 与人最大的区别是:人知道什么时候该停下来给答案,Agent 会一直"想"下去。你给 Agent 接…

2026/7/22 0:01:17阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/21 22:53:50阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/21 18:53:30阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/21 18:53:30阅读更多 →