发布时间:2026/8/25 21:48:35
MyBatis-Plus 高级用法 一、MyBatis-Plus 高级用法整体体系可以把 MyBatis-Plus 高级功能分成下面几层MyBatis-Plus │ ├── 1. 高级查询 │ ├── LambdaQueryWrapper │ ├── LambdaUpdateWrapper │ ├── 条件嵌套 │ ├── select 指定字段 │ ├── groupBy / having │ ├── exists / notExists │ └── apply / last │ ├── 2. 分页与批量 │ ├── PaginationInnerInterceptor │ ├── Page │ ├── selectPage │ ├── saveBatch │ └── updateBatchById │ ├── 3. 数据自动处理 │ ├── 自动填充 │ ├── 逻辑删除 │ ├── 枚举映射 │ └── 类型转换 │ ├── 4. 并发控制 │ └── Version 乐观锁 │ ├── 5. 插件体系 │ ├── 分页插件 │ ├── 乐观锁插件 │ ├── 防全表更新删除 │ ├── 多租户 │ ├── 数据权限 │ └── 动态表名 │ ├── 6. 自定义 SQL │ ├── Select │ ├── XML │ ├── Wrapper 参数 │ └── 自定义 Mapper │ └── 7. 企业级架构 ├── 多租户 ├── 数据权限 ├── 审计字段 ├── 分库分表 └── 权限过滤下面重点讲。二、LambdaQueryWrapper —— 最重要的高级查询方式如果你以前写QueryWrapperUserwrappernewQueryWrapper();wrapper.eq(username,admin).gt(age,18);更推荐LambdaQueryWrapperUserwrappernewLambdaQueryWrapper();wrapper.eq(User::getUsername,admin).gt(User::getAge,18);这样最大的好处是User::getUsername不会出现字符串字段写错的问题。例如wrapper.eq(User::getUserName,username)如果以后数据库字段或者 Java 属性发生变化IDE 可以帮助你发现问题。三、动态条件查询这是实际开发中非常常见的。例如publicListUsergetUserList(Stringusername,Integerage){LambdaQueryWrapperUserwrappernewLambdaQueryWrapper();wrapper.eq(StringUtils.hasText(username),User::getUsername,username).eq(age!null,User::getAge,age);returnuserMapper.selectList(wrapper);}如果username 张三 age null实际 SQL 类似WHEREusername张三如果username null age 20则WHEREage20这比手动拼接 SQL 优雅很多。四、条件嵌套这个在复杂查询中非常有用。例如WHEREusername张三AND(age18ORstatus1)MyBatis-Pluswrapper.eq(User::getUsername,张三).and(w-w.gt(User::getAge,18).or().eq(User::getStatus,1));还可以wrapper.and(w-w.eq(User::getStatus,1).or().eq(User::getStatus,2));这种方式对于后台管理系统的复杂搜索条件特别实用。五、select 指定查询字段很多人使用userMapper.selectList(wrapper);实际上会查询完整字段。如果表非常大没必要全部查询。可以wrapper.select(User::getId,User::getUsername,User::getEmail);最终类似SELECTid,username,emailFROMuser这个在用户列表下拉框搜索结果大数据量查询中特别有价值。六、groupBy / havingMyBatis-Plus 不只是简单 CRUD。例如SELECTdepartment_id,COUNT(*)FROMuserGROUPBYdepartment_idHAVINGCOUNT(*)10可以QueryWrapperUserwrappernewQueryWrapper();wrapper.select(department_id,COUNT(*) AS total).groupBy(department_id).having(COUNT(*) 10);这种场景一般用于统计报表 数据分析 后台 Dashboard七、apply / last —— 非常强但要谨慎例如wrapper.apply(DATE(create_time) {0},2026-08-24);可以执行一些复杂 SQL 条件。或者wrapper.last(LIMIT 10);生成LIMIT10但是last()不要直接拼接用户输入。例如不要wrapper.last(LIMIT userInput);否则存在 SQL 注入风险。八、分页查询这是 MyBatis-Plus 最常用的高级功能之一。配置分页插件BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptorinterceptornewMybatisPlusInterceptor();interceptor.addInnerInterceptor(newPaginationInnerInterceptor(DbType.MYSQL));returninterceptor;}然后PageUserpagenewPage(1,10);PageUserresultuserMapper.selectPage(page,wrapper);可以获取result.getRecords();result.getTotal();result.getCurrent();result.getSize();result.getPages();非常适合前端page pageSize total records这种接口结构。九、自定义分页查询实际项目里经常不是简单selectPage()而是SELECTu.id,u.username,d.nameASdepartment_nameFROMuseruLEFTJOINdepartment dONu.department_idd.id这时候可以自定义 Mapper。例如IPageUserVOselectUserPage(PageUserVOpage,Param(username)Stringusername);XMLselectidselectUserPageresultTypecom.xxx.vo.UserVOSELECT u.id, u.username, d.name AS departmentName FROM user u LEFT JOIN department d ON u.department_id d.idwhereiftestusername ! null and username ! AND u.username LIKE CONCAT(%, #{username}, %)/if/where/select调用PageUserVOpagenewPage(1,10);IPageUserVOresultuserMapper.selectUserPage(page,username);这个是实际企业项目非常重要的能力。十、批量操作MyBatis-Plus 提供saveBatch()例如ListUserusersnewArrayList();users.add(user1);users.add(user2);users.add(user3);userService.saveBatch(users);还可以userService.saveBatch(users,500);表示每 500 条执行一次更新也有userService.updateBatchById(users);实际开发中导入Excel CSV 批量用户 批量题目 批量考试记录都非常常用。十一、逻辑删除例如数据库id username deleted实体TableLogicprivateIntegerdeleted;数据库0 正常 1 删除执行userMapper.deleteById(1);不会真正DELETEFROMuserWHEREid1而是UPDATEuserSETdeleted1WHEREid1同时普通查询selectList()会自动增加WHEREdeleted0这对用户 订单 课程 考试记录 学习记录非常常见。十二、自动填充比如每张表都有create_time update_time create_by update_by实体TableField(fillFieldFill.INSERT)privateLocalDateTimecreateTime;TableField(fillFieldFill.INSERT_UPDATE)privateLocalDateTimeupdateTime;然后ComponentpublicclassMetaObjectHandlerImplimplementsMetaObjectHandler{OverridepublicvoidinsertFill(MetaObjectmetaObject){this.strictInsertFill(metaObject,createTime,LocalDateTime.class,LocalDateTime.now());}OverridepublicvoidupdateFill(MetaObjectmetaObject){this.strictUpdateFill(metaObject,updateTime,LocalDateTime.class,LocalDateTime.now());}}以后userService.save(user);你不需要自己user.setCreateTime(...)框架自动处理。十三、乐观锁 Version这个非常值得掌握。假设用户 A 打开商品 用户 B 打开商品数据库stock 10 version 1A 修改stock 9 version 2B 此时还是version 1B 再修改UPDATEproductSETstock8,version2WHEREid1ANDversion1因为数据库已经version 2所以更新失败实体VersionprivateIntegerversion;配置BeanpublicMybatisPlusInterceptorinterceptor(){MybatisPlusInterceptorinterceptornewMybatisPlusInterceptor();interceptor.addInnerInterceptor(newOptimisticLockerInnerInterceptor());returninterceptor;}适用于库存 订单 账户余额 积分 考试次数 课程状态等并发修改场景。十四、防止全表 UPDATE / DELETE这是非常实用但很多人不知道的功能。例如代码出现userMapper.delete(null);可能直接变成DELETEFROMuser;这是非常危险的。可以使用BlockAttackInnerInterceptor例如interceptor.addInnerInterceptor(newBlockAttackInnerInterceptor());它可以阻止类似UPDATEuserSETstatus1;或者DELETEFROMuser;这种没有 WHERE 条件的危险 SQL。生产项目建议开启。十五、枚举自动映射例如publicenumUserStatus{DISABLED(0,禁用),ENABLED(1,正常);privatefinalIntegercode;privatefinalStringname;}数据库status 1JavaprivateUserStatusstatus;可以通过 MyBatis-Plus 的枚举能力实现EnumValueprivateIntegercode;这样数据库1自动转换成UserStatus.ENABLED比到处if(status1)更清晰。十六、自定义 SQL Wrapper这是一个非常重要的高级组合。假设你有LambdaQueryWrapperUserwrapper同时又需要自己写复杂 SQL。可以让 Wrapper 参与 XML SQL。例如IPageUserVOselectUserPage(PageUserVOpage,Param(Constants.WRAPPER)WrapperUserwrapper);XMLselectidselectUserPageresultTypecom.xxx.vo.UserVOSELECT u.id, u.username, u.email FROM user u ${ew.customSqlSegment}/selectJavaLambdaQueryWrapperUserwrappernewLambdaQueryWrapper();wrapper.eq(User::getStatus,1).like(User::getUsername,keyword);userMapper.selectUserPage(page,wrapper);这样就实现复杂 SQL MyBatis-Plus 条件构造器这是实际项目中非常好用的一种模式。十七、Service 层高级用法MyBatis-Plus 不只是 Mapper。通常publicinterfaceUserServiceextendsIServiceUser{}实现ServicepublicclassUserServiceImplextendsServiceImplUserMapper,UserimplementsUserService{}直接获得save()saveBatch()removeById()updateById()updateBatchById()getById()list()listByIds()count()page()例如userService.getById(id);userService.list();userService.count();userService.save(user);userService.updateById(user);十八、Service 层事务 批量操作例如创建订单TransactionalpublicvoidcreateOrder(OrderDTOdto){OrderordercreateOrder(dto);save(order);ListOrderItemitemscreateItems(dto);orderItemService.saveBatch(items);}如果订单保存成功 订单明细保存失败事务会回滚。这也是 MyBatis-Plus 和 Spring Boot 常见的组合。十九、多租户如果你的系统未来是 SaaS公司 A 公司 B 公司 C数据库user id tenant_id username用户 Atenant_id 1001用户 Btenant_id 1002查询userMapper.selectList(wrapper);框架自动增加WHEREtenant_id1001这就是 MyBatis-Plus 的TenantLineInnerInterceptor非常适合SaaS 教育平台 企业管理系统 多机构系统二十、数据权限这个和多租户很容易混淆。例如超级管理员 → 看所有数据 校长 → 看整个学校 老师 → 看自己的班级 学生 → 只能看自己的数据最终 SQL 可能需要WHEREschool_id1001ANDclass_id2001MyBatis-Plus 可以通过插件机制实现数据权限拦截。但这里需要注意数据权限通常不是简单加一个注解就完全解决。实际项目一般会结合Spring Security Sa-Token RBAC 自定义 SQL 拦截器 MyBatis-Plus InnerInterceptor一起设计。二十一、动态表名例如user_2025 user_2026 user_2027或者log_202608 log_202609可以使用DynamicTableNameInnerInterceptor根据当前请求动态决定表名。例如tableNameHandler根据当前月份 租户 业务类型决定最终访问log_202608这种一般用于日志、流水、历史数据。二十二、MyBatis-Plus 插件体系如果你真正想把 MyBatis-Plus 学到高级阶段我建议重点理解MybatisPlusInterceptor例如BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptorinterceptornewMybatisPlusInterceptor();// 分页interceptor.addInnerInterceptor(newPaginationInnerInterceptor(DbType.MYSQL));// 乐观锁interceptor.addInnerInterceptor(newOptimisticLockerInnerInterceptor());// 防止全表更新删除interceptor.addInnerInterceptor(newBlockAttackInnerInterceptor());returninterceptor;}整个 MyBatis-Plus 的高级能力本质上很多都围绕Interceptor展开。二十三、一个比较完整的企业级配置例如ConfigurationMapperScan(com.example.mapper)publicclassMybatisPlusConfig{BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptorinterceptornewMybatisPlusInterceptor();// 分页interceptor.addInnerInterceptor(newPaginationInnerInterceptor(DbType.MYSQL));// 乐观锁interceptor.addInnerInterceptor(newOptimisticLockerInnerInterceptor());// 防止全表更新、删除interceptor.addInnerInterceptor(newBlockAttackInnerInterceptor());returninterceptor;}}这已经是一个比较常见的生产级基础配置。二十四、MyBatis-Plus 和原生 MyBatis 怎么配合这是非常重要的一点。不要认为用了 MyBatis-Plus 就不能写 XML。实际上推荐简单 CRUD ↓ MyBatis-Plus 简单条件查询 ↓ LambdaQueryWrapper 复杂查询 ↓ MyBatis XML 多表 JOIN ↓ XML / 自定义 Mapper 复杂统计 ↓ XML 特殊 SQL ↓ 原生 MyBatis例如userMapper.selectById(id);用 MP。但是用户 ↓ 部门 ↓ 角色 ↓ 权限 ↓ 课程 ↓ 学习记录这种复杂查询直接写 XML 往往比强行使用 Wrapper 更合理。二十五、真正值得你掌握的几个高级组合如果你是为了面试 实际项目开发我建议重点掌握下面几个组合。① Lambda 动态条件LambdaQueryWrapper 条件判断这是日常开发最高频。② MP 分页Page LambdaQueryWrapper PaginationInnerInterceptor后台管理系统基本必用。③ MP XMLMyBatis-Plus CRUD 自定义 Mapper XML这是企业项目最实用的组合。④ 自动填充 逻辑删除TableLogic MetaObjectHandler非常适合管理系统。⑤ 乐观锁 事务Version Transactional解决并发更新问题。⑥ 插件体系重点理解MybatisPlusInterceptor │ ├── PaginationInnerInterceptor ├── OptimisticLockerInnerInterceptor ├── BlockAttackInnerInterceptor ├── TenantLineInnerInterceptor ├── DataPermissionInterceptor └── DynamicTableNameInnerInterceptor这个层面掌握以后你对 MyBatis-Plus 的理解就从“会 CRUD”提升到“理解框架”。

相关新闻

2026/8/25 21:43:35

GraphRAG深度认识:当大模型学会“理解关系”

引言:RAG的“天花板”与GraphRAG的破局检索增强生成(RAG)在过去两年里几乎成了每个AI应用的标配。通过从外部知识库中检索相关信息并注入大语言模型(LLM)的提示词中,RAG有效缓解了幻觉、知识陈旧和缺乏领域…

2026/8/26 0:04:32

Python random 模块常用函数详解:从入门到实战

目录 1. 引言2. 准备工作3. 基础随机函数4. 序列相关函数5. 随机种子与复现6. 实战案例7. 注意事项8. 常见问题与排查9. 总结 1. 引言 摘要: 本文系统介绍 Python 标准库 random 模块中最常用的随机数生成函数。内容涵盖基础随机函数(random()、unifor…

2026/8/25 23:59:31

基于微信小程序的篮球场馆预订系统(源码+LW+部署讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/25 23:59:31

缓存穿透、击穿与雪崩:原理、区别与Spring Boot+Redis实战解决方案

大家好,我是专注于后端技术分享的博主。在构建高并发系统时,缓存是提升性能、保护数据库的利器。然而,如果使用不当,缓存也可能成为系统稳定性的“阿喀琉斯之踵”。缓存穿透、击穿和雪崩是三个高频出现且极易混淆的故障场景&#…

2026/8/25 23:59:31

免费AI大模型调教指南:打造专属网文写作助手

1. 先搞清楚“AI小说扩展模式”到底能帮你做什么如果你是一个刚开始写网文、或者卡在L3级别以下的作者,最头疼的可能是情节推进不下去、人物对话干瘪,或者世界观设定不够丰满。自己对着空白文档硬憋,效率很低。这时候,一个能理解你…

2026/8/25 23:59:31

Hermes接入团队协作后,我推翻了三个效率假设

聊《Hermes真能提效吗?先看流程里最慢的那一步》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。摘要团队把 Hermes 接进项目三个月后,交付速度没有提升反而慢了。复盘后发现,最先…

2026/8/25 1:04:19

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/25 11:48:27

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/25 16:56:43

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/26 0:04:32

Python random 模块常用函数详解:从入门到实战

目录 1. 引言2. 准备工作3. 基础随机函数4. 序列相关函数5. 随机种子与复现6. 实战案例7. 注意事项8. 常见问题与排查9. 总结 1. 引言 摘要: 本文系统介绍 Python 标准库 random 模块中最常用的随机数生成函数。内容涵盖基础随机函数(random()、unifor…

2026/8/24 13:42:17

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/24 18:13:48

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/25 1:08:14

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…