从源码到代码:MyBatis-Flex 与 MyBatis-Plus 的逐项对比

发布时间:2026/8/25 11:12:16

从源码到代码:MyBatis-Flex 与 MyBatis-Plus 的逐项对比
社区里好多程序员在讨论MyBatis-Flex说它轻量、快、设计优雅。好奇心驱动下载了源码搭建了一个demo工程认认真真学了一遍。过程中发现它和MyBatis-Plus的设计思路差异不小记录下来做个对比。这篇文章不评价谁好谁差只是从源码和实际代码两个层面看看这两个框架到底有什么不同。demo工程用的订单表和订单明细表Spring Boot 2.7MyBatis-Flex 1.11.8。同一张订单表两种写法先来段最简单的代码对同一张表两个框架的代码长什么样。实体类MyBatis-Flex的实体类用Table和Id注解Table(order)DatapublicclassOrder{Id(keyTypeKeyType.Auto)privateLongid;privateStringorderNo;privateLonguserId;privateBigDecimaltotalAmount;privateIntegerstatus;privateLocalDateTimecreateTime;}MyBatis-Plus的写法大家应该都很熟悉了TableName和TableIdTableName(order)DatapublicclassOrder{TableId(typeIdType.AUTO)privateLongid;privateStringorderNo;privateLonguserId;privateBigDecimaltotalAmount;privateIntegerstatus;privateLocalDateTimecreateTime;}注解名不同但做的事情一样。真正的差异在查询条件的构建方式上。条件查询查某个用户的所有已支付订单按创建时间倒序。MyBatis-Plus用LambdaQueryWrapperLambdaQueryWrapperOrderwrappernewLambdaQueryWrapper();wrapper.eq(Order::getUserId,userId).eq(Order::getStatus,1).orderByDesc(Order::getCreateTime);ListOrderordersorderMapper.selectList(wrapper);MyBatis-Flex用QueryWrapper但条件构建方式完全不同QueryWrapperqueryQueryWrapper.create().where(ORDER.USER_ID.eq(userId)).and(ORDER.STATUS.eq(1)).orderBy(ORDER.CREATE_TIME.desc());ListOrderordersorderMapper.selectListByQuery(query);注意这里的ORDER不是字符串是一个编译期自动生成的类。ORDER.USER_ID、ORDER.STATUS都是这个类里的常量字段。写错了字段名编译直接报错不需要等到运行时才发现。这个ORDER类是怎么来的后面讲架构差异的时候会详细说。分页查询MyBatis-Plus的分页需要先配置拦截器然后创建Page对象// 需要先配置 MybatisPlusInterceptor PaginationInnerInterceptorPageOrderpagenewPage(1,10);orderMapper.selectPage(page,wrapper);MyBatis-Flex的分页是内建的不需要配置拦截器直接调paginate()PageOrderpageorderMapper.paginate(1,10,query);看起来只是一个方法调用的区别背后是两个框架在架构设计上的根本分歧。架构上的根本差异写法不同只是表象在设计层面上看它们生成SQL的方式是不同的。MyBatis-Plus启动期注入MyBatis-Plus在MyBatis启动阶段通过AbstractSqlInjector为每个Mapper接口注入CRUD对应的MappedStatement。每个操作背后都有一个专门的类来负责拼SQLInsert类负责插入DeleteById类负责按ID删除SelectList类负责列表查询等等。这些类都是AbstractMethod的子类。启动时AbstractSqlInjector遍历所有注册的AbstractMethod为每个Mapper逐个注入。MyBatis-Plus是在MyBatis原有的XML解析机制之上做扩展。它把CRUD操作的SQL模板预编译好注册到MyBatis的Configuration里运行时直接拿来用。这套机制的代价是每个Mapper接口不管你用不用启动时都会注入一整套CRUD方法。MyBatis-FlexProvider注解MyBatis-Flex走了一条完全不同的路。它的BaseMapper上的方法用的是MyBatis原生的SelectProvider、InsertProvider等注解指向一个EntitySqlProvider类。SQL不是在启动时预生成的而是在运行时由Provider动态拼出来的。调用orderMapper.selectOneById(1)的时候MyBatis会调用EntitySqlProvider里对应的方法这个方法根据实体类的元数据表名、字段、主键等实时拼出一条SQL。这种设计带来了MyBatis-Flex官网一直在强调的「三个轻」轻依赖整个框架只依赖MyBatis没有其他任何第三方依赖。轻实现没有拦截器。MyBatis-Plus的分页、租户、乐观锁等功能都是通过拦截器实现的MyBatis-Flex把这些能力直接内建在core里不走拦截器。轻运行没有SQL解析。MyBatis-Plus的拦截器在执行前会解析原始SQL比如分页拦截器要解析SQL来生成count语句MyBatis-Flex直接拼SQL不需要解析。APT编译期代码生成前面条件查询里用到的ORDER类不是手写的是编译期自动生成的。MyBatis-Flex用了一个叫APTAnnotation Processing Tool的技术和Lombok的原理类似。在mvn compile的时候mybatis-flex-processor模块会扫描所有带Table注解的实体类自动生成两样东西一个是TableDef类比如OrderTableDef里面包含每个字段对应的QueryColumn常量。ORDER.USER_ID就是OrderTableDef里的一个QueryColumn它知道这个字段对应哪张表的哪一列。另一个是Mapper接口。如果项目里没有手写MapperAPT会自动生成一个继承BaseMapper的接口。这套机制的好处是查询条件的构建是类型安全的。ORDER.USER_NAME假设有这个字段写错了字段名IDE直接标红编译都过不了。MyBatis-Plus的Lambda方式也能做到编译期检查但它依赖实体类的getter方法Flex这边不需要直接引用字段常量就行。不过这个设计也有代价用MyBatis-Flex写查询你得知道两个类——Order实体和ORDERAPT生成的TableDef。新人刚接触的时候可能会懵这个ORDER是哪来的它在源码里看不到是编译后才会出现的类。而用MyBatis-Plus只需要知道Order一个类就够了Order::getUserId这种方法引用很直观不需要理解额外的生成机制。社区里讨论框架选型的时候不少人提到MyBatis-Flex的学习曲线比Plus陡APT生成的这些类就是原因之一。那这个取舍值不值Flex用「多一个类」换来的是不依赖getter方法、支持多表join、QueryWrapper可序列化传输。这些都是Plus的Lambda方式做不到的。但如果你只是做单表CRUDPlus的方式确实更简单直接。多表查询差异最大的地方单表CRUD两个框架差别不大真正与众不同的是多表查询。假设要查询已支付订单及其明细在MyBatis-Plus里QueryWrapper不支持join你得手写XMLselectidlistWithDetailresultTypeOrderSELECT o.*, d.product_name, d.price, d.quantity FROM order o LEFT JOIN order_detail d ON o.id d.order_id WHERE o.status 1/selectMapper接口里还得加一个对应的方法声明。代码量不多但每个多表查询都得这么写一遍。在MyBatis-Flex里QueryWrapper直接支持leftJoinQueryWrapperqueryQueryWrapper.create().select().from(ORDER).leftJoin(ORDER_DETAIL).on(ORDER.ID.eq(ORDER_DETAIL.ORDER_ID)).where(ORDER.STATUS.eq(1));ListOrderordersorderMapper.selectListByQuery(query);不需要写XML不需要额外声明Mapper方法。join条件用的是编译期生成的QueryColumn字段名写错了编译就报错。这个差异在项目里影响很大。用过MyBatis-Plus的人都知道稍微复杂一点的查询最终都得回到XMLQueryWrapper能覆盖的场景其实有限。MyBatis-Flex的QueryWrapper覆盖面更广大多数场景都能在Java代码里完成。QueryWrapper的设计差异两个框架的QueryWrapper虽然名字一样但设计思路完全不同。MyBatis-Plus的QueryWrapper是泛型的QueryWrapperT。条件构建有两种方式字符串字段名wrapper.eq(user_name, sam)和Lambda方法引用wrapper.eq(User::getUserName, sam)。字符串方式容易写错字段名Lambda方式解决了这个问题但要求实体类必须有对应的getter方法。MyBatis-Flex的QueryWrapper不带泛型。条件通过APT生成的QueryColumn来构建ORDER.USER_NAME.eq(sam)这种写法。字段引用是编译期常量天然类型安全不依赖实体类的getter方法。还有一个容易忽略的差异MyBatis-Flex的QueryWrapper支持序列化和RPC传输。在微服务架构下一个服务构建的QueryWrapper可以通过RPC传给另一个服务执行。MyBatis-Plus的Wrapper内部持有Lambda表达式引用不支持序列化传输。另外MyBatis-Flex的QueryWrapper在遇到null值时会自动忽略该条件不需要手动判断。MyBatis-Plus需要用wrapper.eq(value ! null, column, value)来处理动态条件。部分字段更新更新订单状态只改status字段其他字段不动。MyBatis-Plus用UpdateWrapper的set方法显式指定要更新的字段UpdateWrapperOrderwrappernewUpdateWrapper();wrapper.eq(id,orderId).set(status,2).set(total_amount,newBigDecimal(0.00));orderMapper.update(null,wrapper);MyBatis-Flex用UpdateEntity只更新调了setter的字段OrderorderUpdateEntity.of(Order.class,orderId);order.setStatus(2);order.setTotalAmount(newBigDecimal(0.00));orderMapper.update(order);UpdateEntity创建的代理对象会记录每个setter调用最终只把这些字段写进UPDATE语句。没调setter的字段不管实体对象里的值是什么都不会出现在SQL里。这个设计还有一个很实用的好处可以把某个字段从有值更新为null。在MyBatis-Plus里updateById默认忽略null值你传个null进去它不更新。想置空某个字段就得额外再调一次updateorderMapper.updateById(order);// 想置空remark还得再补一次if(order.getRemark()null){orderMapper.update(null,newLambdaUpdateWrapperOrder().eq(Order::getId,order.getId()).set(Order::getRemark,null));}这种写法用过的应该都懂不优雅但没办法。UpdateEntity就不存在这个问题你调了order.setRemark(null)它就给你更新为null不需要二次操作。Db Row无实体类操作这是MyBatis-Flex独有的能力MyBatis-Plus没有。Db是一个工具类Row是HashMap的子类。两者配合可以在没有实体类的情况下直接操作数据库RowrownewRow();row.set(order_no,ORD20250703002);row.set(user_id,1004L);row.set(total_amount,newBigDecimal(66.00));row.set(status,0);Db.insert(order,row);适合写临时脚本、做数据迁移、或者处理一些不固定的动态表结构。不需要为每张表都定义一个实体类。查询也行用QueryWrapper构建条件调Db.paginate()就完事了。功能对比整理了一张对比表方便选型时参考对比维度MyBatis-Plus 3.xMyBatis-FlexSQL生成方式启动期注入MappedStatement运行时Provider注解拦截器分页、租户等靠拦截器实现没有拦截器SQL解析拦截器内解析原始SQL不解析直接拼SQL第三方依赖coreextensionstarter只依赖MyBatis条件查询类型安全LambdaQueryWrapper方法引用APT生成QueryColumn编译期常量条件为null时需要手动判断自动忽略分页实现拦截器需额外配置内建在core多表查询需要手写XMLQueryWrapper直接joinQueryWrapper序列化不支持支持RPC传输无实体类操作不支持Db Row部分字段更新UpdateWrapper.set()UpdateEntity.of()多主键/复合主键不支持支持数据脱敏/字段加密收费功能免费生态和社区成熟文档丰富用户多较新社区较小学习成本低上手快需要理解APT小结两个框架不是谁替代谁的关系设计取向不同。MyBatis-Plus走的是「在MyBatis之上尽可能多扩展」的路线。功能全拦截器机制让它的扩展点很多生态也成熟。文档多遇到问题搜一下基本都能找到答案。代价是体积不小拦截器和SQL解析带来额外的复杂度多表查询最终还是要回到XML。MyBatis-Flex走的是「极简轻量」的路线。没有拦截器、没有SQL解析、零第三方依赖QueryWrapper直接支持多表joinAPT生成类型安全的查询条件。这些设计在工程上确实干净。代价是生态薄社区小遇到问题能查的资料不多。老项目用着MyBatis-Plus没必要换生态成熟这个优势不是技术层面能衡量的。新项目如果团队愿意花点时间熟悉MyBatis-Flex值得试试尤其是多表查询多的场景能少写不少XML。参考的内容MyBatis-Flex官网MyBatis-Flex和同类框架功能对比MyBatis-Flex源码版本1.11.8MyBatis-Plus源码版本3.x

相关新闻

xbatis-ddl-auto:轻量自动建表工具,功能丰富且安全有保障!

xbatis-ddl-auto:轻量自动建表工具,功能丰富且安全有保障!

2026/8/22 17:34:39

xbatis-ddl-auto简介xbatis-ddl-auto是一个基于xbatis实体元数据的轻量自动建表工具。它复用xbatis的 Table、TableId、TableField、ColumnDefinition等注解解析结果,根据实体类生成并执行数据库DDL,提供接近JPA ddl-autocreate/update的使用体验&#x…

NoFences:终极免费Windows桌面分区工具,3分钟告别杂乱桌面

NoFences:终极免费Windows桌面分区工具,3分钟告别杂乱桌面

2026/8/22 12:32:06

NoFences:终极免费Windows桌面分区工具,3分钟告别杂乱桌面 【免费下载链接】NoFences 🚧 Open Source Stardock Fences alternative 项目地址: https://gitcode.com/gh_mirrors/no/NoFences 你是否厌倦了在混乱的Windows桌面上寻找文件…

【小白也能轻松玩转龙虾】虾壳云一键部署新手专属包,专门适配零基础用户安装(附最新安装包)

【小白也能轻松玩转龙虾】虾壳云一键部署新手专属包,专门适配零基础用户安装(附最新安装包)

2026/8/22 17:34:41

OpenClaw(小龙虾)Windows 一键部署实操手册|十分钟搭建专属本地数字员工 适配平台:Windows 10/11(64 位)|零基础友好|全可视化界面|无编程门槛 当下热度较高的开源 AI 智…

基于POMDP与强化学习的临床诊断AI:解决医疗AI落地最后一公里难题

基于POMDP与强化学习的临床诊断AI:解决医疗AI落地最后一公里难题

2026/8/25 11:05:04

1. 从理想实验室到嘈杂诊室:临床诊断AI的“最后一公里”难题如果你关注过医疗AI的发展,可能会发现一个有趣的现象:很多在论文里表现惊艳的模型,一旦放到真实的医院场景里,表现就大打折扣。这背后的核心矛盾&#xff0c…

前后端大整数精度丢失:雪花算法ID在JSON传输中的解决方案

前后端大整数精度丢失:雪花算法ID在JSON传输中的解决方案

2026/8/25 11:05:04

1. 问题缘起:一个看似简单却普遍存在的“坑” 最近在做一个用户中心模块的后端重构,数据库主键从自增整数换成了雪花算法生成的64位长整型(Java里的 Long )。本地测试、接口调试一切正常,数据增删改查流畅无比。然而…

基于结构因果模型的LLM智能体对手建模:从黑箱预测到白盒推理

基于结构因果模型的LLM智能体对手建模:从黑箱预测到白盒推理

2026/8/25 11:05:04

1. 项目概述:当LLM智能体学会“读心术”最近在折腾多智能体系统,一个绕不开的痛点就是智能体间的交互。想象一下,你设计了一个谈判场景,让两个基于大语言模型的智能体去讨价还价。它们可以基于自己的目标和历史对话生成回复&#…

无线控制新范式:执行器侧渐进风险门控驱动技术解析

无线控制新范式:执行器侧渐进风险门控驱动技术解析

2026/8/25 11:05:04

1. 项目概述:无线监督控制中的执行器侧渐进风险门控驱动最近在工业自动化和边缘计算领域,一个名为“Executor-Side Progressive Risk-Gated Actuation for Agentic AI in Wireless Supervisory Control”的概念开始被频繁讨论。这串英文看着挺唬人&#…

LLM Agent承诺完整性评估:NeuroState-Bench基准与工程实践

LLM Agent承诺完整性评估:NeuroState-Bench基准与工程实践

2026/8/25 11:05:04

1. 项目缘起:当LLM Agent开始“说一套做一套”最近在折腾LLM Agent(大型语言模型智能体)的朋友,估计都遇到过一种让人头疼的情况:你精心设计了一个Agent,给它设定了明确的角色、目标和行为准则,…

性能分析-帧渲染跟踪

性能分析-帧渲染跟踪

2026/8/25 10:55:04

Flutter OH 应用进行性能分析时,需利用分析工具捕获应用的trace数据,并对其进行分析。鉴于Flutter应用中可能会出现需要单独追踪某帧渲染的情况,如帧率卡顿或帧丢失,本文特介绍了一种针对单帧追踪的方法。 分析工具 常用的分析工…

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

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

2026/8/24 19:53:32

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

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

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

2026/8/24 19:56:07

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

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

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

2026/8/24 21:16:09

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

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南

2026/8/25 0:04:34

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory Meta Description:GetQzonehistory 是一个QQ空间历史说…

洛谷 P7912:[CSP-J 2021 T4] 小熊的果篮 ← 双向链表

洛谷 P7912:[CSP-J 2021 T4] 小熊的果篮 ← 双向链表

2026/8/25 0:04:35

【题目来源】 https://www.luogu.com.cn/problem/P7912 【题目描述】 小熊的水果店里摆放着一排 n 个水果。每个水果只可能是苹果或桔子,从左到右依次用正整数 1,2,…,n 编号。连续排在一起的同一种水果称为一个“块”。小熊要把这一排水果挑到若干个果篮里&#x…

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG

2026/8/25 0:04:35

Transformers.js 网页端图像抠图实战:零后端 3 行代码返回透明 PNG 【免费下载链接】transformers.js State-of-the-art Machine Learning for the web. Run 🤗 Transformers directly in your browser, with no need for a server! 项目地址: https:/…

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

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

2026/8/22 2:02:26

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

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/22 4:13:47

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

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/22 1:32:34

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…