Mybatis增强版MyBatis-Flex简介
Mybatis增强版:Mybatis-Plus(使用的最多,老牌Mybatis增强框架,2016年开源)、Fluent-MyBatis(阿里云开发的Mybatis增强框架,来自阿里云.云效产品团队)、Mybatis-Flex。
Flex英文单词意思是灵活,Mybatis-Flex官方文档中多处强调‘灵活’一词。
1、对比特性
功能或特点 | MyBatis-Flex | MyBatis-Plus | Fluent-MyBatis |
---|---|---|---|
对 entity 的基本增删改查 | ✅ | ✅ | ✅ |
分页查询 | ✅ | ✅ | ✅ |
分页查询之总量缓存 | ✅ | ✅ | ❌ |
分页查询无 SQL 解析设计(更轻量,及更高性能) | ✅ | ❌ | ✅ |
多表查询:from 多张表 | ✅ | ❌ | ❌ |
多表查询: left join、inner join 等等 | ✅ | ❌ | ✅ |
多表查询: union,union all | ✅ | ❌ | ✅ |
单主键配置 | ✅ | ✅ | ✅ |
多种 id 生成策略 | ✅ | ✅ | ✅ |
支持多主键、复合主键 | ✅ | ❌ | ❌ |
字段的 typeHandler 配置 | ✅ | ✅ | ✅ |
除了 MyBatis,无其他第三方依赖(更轻量) | ✅ | ❌ | ❌ |
QueryWrapper 是否支持在微服务项目下进行 RPC 传输 | ✅ | ❌ | 未知 |
逻辑删除 | ✅ | ✅ | ✅ |
乐观锁 | ✅ | ✅ | ✅ |
SQL 审计 | ✅ | ❌ | ❌ |
数据填充 | ✅ | ✔️ (收费) | ✅ |
数据脱敏 | ✅ | ✔️ (收费) | ❌ |
字段权限 | ✅ | ✔️ (收费) | ❌ |
字段加密 | ✅ | ✔️ (收费) | ❌ |
字典回写 | ✅ | ✔️ (收费) | ❌ |
Db + Row | ✅ | ❌ | ❌ |
Entity 监听 | ✅ | ❌ | ❌ |
多数据源支持 | ✅ | 借助其他框架或收费 | ❌ |
多数据源是否支持 Spring 的事务管理,比如 @Transactional 和 TransactionTemplate 等 | ✅ | ❌ | ❌ |
多数据源是否支持 “非Spring” 项目 | ✅ | ❌ | ❌ |
多租户 | ✅ | ✅ | ❌ |
动态表名 | ✅ | ✅ | ❌ |
动态 Schema | ✅ | ❌ | ❌ |
总的来说,Mybatis-Flex相对于Mybatis-Plus较为显著的特点是,多了联表查询和在Mybatis-plus中收费的Mybatis-Flex免费使用。
联表查询在日常开发中使用的比较多,Mybatis-Flex支持这个,还是很不错的。
下面简单介绍一下Mybatis-Flex关于联表查询。
2、Mybatis-Flex联表查询
在 MyBatis-Flex 中,内置了 3 种方案进行联表查询,比如 一对多、一对一、多对一、多对多等场景,它们分别是:
方案1:Relations 注解
方案2:Field Query
方案3:Join Query
方案1:Relations 注解
在 MyBatis-Flex 中,提供了 4 个 Relations 注解,他们分别是:
RelationOneToOne:用于一对一的场景
RelationOneToMany:用于一对多的场景
RelationManyToOne:用于多对一的场景
RelationManyToMany:用于多对多的场景
添加了以上配置的实体类,在通过 BaseMapper 的方法查询数据时,需要调用 select***WithRelations() 方法,Relations 注解才能生效。 否则 MyBatis-Flex 自动忽略 Relations 注解。
BaseMapper 提供的 withRelations 方法。
一对一 @RelationOneToOne
假设有一个账户,账户有身份证,账户和身份证的关系是一对一的关系,代码如下所示:
public class Account implements Serializable {@Id(keyType = KeyType.Auto)private Long id;private String userName;@RelationOneToOne(selfField = "id", targetField = "accountId")private IDCard idCard;//关联字段//getter setter
}
@Table(value = "tb_idcard")
public class IDCard implements Serializable {private Long accountId;private String cardNo;private String content;//getter setter
}
@RelationOneToOne 配置描述:
- selfField 当前实体类的属性
- targetField 目标对象的关系实体类的属性
PS: 若 selfField 是主键,且当前表只有 1 个主键时,可以不填写。因此,以上的配置可以简化为 @RelationOneToOne(targetField = “accountId”)
假设数据库 5 条 Account 数据,然后进行查询:
List<Account> accounts = accountMapper.selectAllWithRelations();
System.out.println(accounts);
其执行的 SQL 如下:
SELECT `id`, `user_name`, `age` FROM `tb_account`SELECT `account_id`, `card_no`, `content` FROM `tb_idcard`
WHERE account_id IN (1, 2, 3, 4, 5)
[Account{id=1, userName='孙悟空', age=18, idCard=IDCard{accountId=1, cardNo='0001', content='内容1'}},Account{id=2, userName='猪八戒', age=19, idCard=IDCard{accountId=2, cardNo='0002', content='内容2'}},Account{id=3, userName='沙和尚', age=19, idCard=IDCard{accountId=3, cardNo='0003', content='内容3'}},Account{id=4, userName='六耳猕猴', age=19, idCard=IDCard{accountId=4, cardNo='0004', content='内容4'}},Account{id=5, userName='王麻子叔叔', age=19, idCard=IDCard{accountId=5, cardNo='0005', content='内容5'}}]
在 Account.java 和 IDCard.java 示例中,若他们的关联关系是通过 中间表 的方式进行关联,则需要添加 joinTable joinSelfColumn joinTargetColumn 配置,如下所示:
public class Account implements Serializable {@Id(keyType = KeyType.Auto)private Long id;private String userName;@RelationOneToOne(joinTable = "tb_idcard_mapping",joinSelfColumn = "account_id",joinTargetColumn = "idcard_id",selfField = "id",targetField = "accountId")private IDCard idCard;//getter setter
}
其他的RelationManyToOne(用于多对一的场景)、RelationManyToMany(用于多对多的场景)和RelationOneToMany(用于一对多的场景)差不多用法,可以查看官网:Mybatis-Flex官网地址
其中还有一点比较好的,就是父子关系查询。
父子关系查询
比如在一些系统中,比如菜单会有一些父子关系,例如菜单表如下:
CREATE TABLE `tb_menu`
(`id` INTEGER auto_increment,`parent_id` INTEGER,`name` VARCHAR(100)
);
Menu.java 定义如下:
@Table(value = "tb_menu")
public class Menu implements Serializable {private Long id;private Long parentId;private String name;@RelationManyToOne(selfField = "parentId", targetField = "id")private Menu parent;@RelationOneToMany(selfField = "id", targetField = "parentId")private List<Menu> children;//getter setter
}
查询顶级菜单:
QueryWrapper qw = QueryWrapper.create();
qw.where(MENU.PARENT_ID.eq(0));List<Menu> menus = menuMapper.selectListWithRelationsByQuery(qw);
System.out.println(JSON.toJSONString(menus));
SQL 执行如下:
SELECT `id`, `parent_id`, `name` FROM `tb_menu` WHERE `parent_id` = 0
SELECT `id`, `parent_id`, `name` FROM `tb_menu` WHERE id = 0
SELECT `id`, `parent_id`, `name` FROM `tb_menu` WHERE parent_id IN (1, 2, 3)
JSON 输出内容如下:
[{"children": [{"id": 4,"name": "子菜单","parentId": 1},{"id": 5,"name": "子菜单","parentId": 1}],"id": 1,"name": "顶级菜单1","parentId": 0},{"children": [],"id": 2,"name": "顶级菜单2","parentId": 0},{"children": [{"id": 6,"name": "子菜单","parentId": 3},{"id": 7,"name": "子菜单","parentId": 3},{"id": 8,"name": "子菜单","parentId": 3}],"id": 3,"name": "顶级菜单3","parentId": 0}
]
在以上的父子关系查询中,默认的递归查询深度为 3 个层级,若需要查询指定递归深度,需要添加如下配置:
QueryWrapper qw = QueryWrapper.create();
qw.where(MENU.PARENT_ID.eq(0));//设置递归查询深度为 10 层
RelationManager.setMaxDepth(10);
List<Menu> menus = menuMapper.selectListWithRelationsByQuery(qw);
RelationManager.setMaxDepth(10) 的配置,只在当前第一次查询有效,查询后会清除设置。
方案2:Field Query
这个方案,不简单明了。大概的代码长下面个样子。
QueryWrapper queryWrapper = QueryWrapper.create().select().from(ARTICLE).where(ARTICLE.id.ge(100));List<Article> articles = mapper.selectListByQuery(queryWrapper, fieldQueryBuilder -> fieldQueryBuilder.field(Article::getCategories) // 或者 .field("categories").queryWrapper(article -> QueryWrapper.create().select().from(CATEGORY).where(CATEGORY.id.in(select("category_id").from("article_category_mapping").where("article_id = ?", article.getId()))));
方案3:Join Query
这个方案也是不咋滴,代码长得如下:
QueryWrapper queryWrapper = QueryWrapper.create().select(USER.USER_ID, USER.USER_NAME, ROLE.ALL_COLUMNS).from(USER.as("u")).leftJoin(USER_ROLE).as("ur").on(USER_ROLE.USER_ID.eq(USER.USER_ID)).leftJoin(ROLE).as("r").on(USER_ROLE.ROLE_ID.eq(ROLE.ROLE_ID));
List<UserVO> userVOS = userMapper.selectListByQueryAs(queryWrapper, UserVO.class);
userVOS.forEach(System.err::println);
方案2和3总的来说,都不怎么行,不过比没有强点。个人使用的话,还是习惯用Mybatis的mapper.xml写法。
其他特性的话,和Mybatis-Plus大同小异。
相关文章:

Mybatis增强版MyBatis-Flex简介
Mybatis增强版:Mybatis-Plus(使用的最多,老牌Mybatis增强框架,2016年开源)、Fluent-MyBatis(阿里云开发的Mybatis增强框架,来自阿里云.云效产品团队)、Mybatis-Flex。 Flex英文单词意思是灵活,Mybatis-Flex官方文档中多…...

MFC第二十一天 CS架构多页面开发与数据交互、CImageList图像列表介绍 、CListCtrl-SetItem设置列表项的方法
文章目录 CImageList图像列表介绍CListCtrl图标的原理CListCtrl列表图标设置CListCtrl-SetItem设置列表项的方法 CS架构多页面开发与数据交互添加用户实现向导多页数据交互pch.hCLientXq.h CAppCPage1.hCPage1.cppCPage2.hCPage2.cppCWorkerDlg .hCWorkerDlg.cpp 多页数据修改C…...

spring boot--自动化注入组件原理、内嵌tomcat-1
前言 我们知道开发spring boot项目,在启动类上添加注解SpringBootApplication ,然后引入要自动注入的组件依赖,然后现application.properties中加上相应配置就可以自动注入这个组件,那么下面看看自动注入组件是如何实现的 一、S…...

短视频矩阵系统源码---开发技术源码能力
短视频矩阵系统开发涉及到多个领域的技术,包括视频编解码技术、大数据处理技术、音视频传输技术、电子商务及支付技术等。因此,短视频矩阵系统开发人员需要具备扎实的计算机基础知识、出色的编程能力、熟练掌握多种开发工具和框架,并掌握音视…...

可观测之调用链Skywalking
简介 分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器(Docker、K8s、Mesos)架构而设计。提供分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案。 多种监控手段。可以通过语言探针和 service mesh 获得监控…...

linux上适用的反汇编调试软件(对标od)
ubuntu下类似于od软件 经过搜索,在Ubuntu上选用edb-debugger进行动态调试, 下载链接: https://github.com/eteran/edb-debugger 但是依赖反汇编引擎: https://github.com/capstone-engine/capstone 安装 先安装capstone 先下载release的版本…...

基于高斯混合模型聚类的风电场短期功率预测方法(Pythonmatlab代码实现)
目录 💥1 概述 📚2 运行结果 2.1 Python 2.2 Matlab 🎉3 参考文献 🌈4 Matlab代码、数据、文章讲解 💥1 概述 文献来源: 摘要:对任意来流条件下的风电场发电功率进行准确预测,是提高电网对风电…...

【深入了解pytorch】PyTorch循环神经网络(RNN)
【深入了解pytorch】PyTorch循环神经网络(RNN) PyTorch循环神经网络(RNN):概念、工作原理与常见变体循环神经网络概念和工作原理RNN的结构RNN的工作原理LSTM(长短期记忆网络)LSTM的结构LSTM的工作原理GRU(门控循环单元)GRU的结构GRU的工作原理在PyTorch中实现RNN、LST…...

电商运营的方法
1、以后干,不如现在干 1.1 做代理,搞研发 1.2 自建店铺,去看其他店铺的设计样板 1.3 记住网店挣钱三要点:装修,物流,产品资源 1.4 记住你的职责,让别人明白怎么做,仔细看资料,搞清楚细节 2、如何打开机器人 3.设置自动回复 Ctrl + tab 4.如何做基础销量,做一个刷…...

Swift 如何确定 scrollView 已经滑动结束
在 iOS 的 UIScrollView 中,你可以通过实现 UIScrollViewDelegate 的方法来检测滑动结束事件。具体来说,你可以实现以下方法: func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {if !decelerat…...

html学习2(css、图像)
1、层叠样式表css是为了更好的渲染html元素而引入的。 2、css添加到html的方式,最好的方式是通过外部引用CSS文件 内联样式- 在HTML元素中使用"style" 属性,当特殊的样式需要应用到个别元素时,就可以使用内联样式。 使用内联样式…...

微服务探索之路06篇k8s配置文件Yaml部署Redis使用Helm部署MongoDB和kafka
1 安装Redis 1.1创建配置文件redis.conf 切换到自己的目录下如本文是放在/home/ubuntu下 cd /home/ubuntuvim redis.conf bind 0.0.0.0 protected-mode yes port 6379 requirepass qwe123456 tcp-backlog 511 timeout 0 tcp-keepalive 300 daemonize no pidfile /var/run/r…...

Microsoft todo 数据导出
文章目录 官方说明: https://support.microsoft.com/zh-cn/office/导出您的-microsoft-待办事项帐户-d286b243-affb-4db4-addc-162e16588943 由于 微软待办 会自动与 Outlook 中的任务同步,因此您可以从 Outlook 中导出所有列表和任务。 若要导出列表和…...

SSIS对SQL Server向Mysql数据转发表数据 (二)
1、在SQL Server数据库创建一个数据库表:users USE [Test1] GO/****** Object: Table [dbo].[users] Script Date: 2023/7/27 16:25:11 ******/ SET ANSI_NULLS ON GOSET QUOTED_IDENTIFIER ON GOCREATE TABLE [dbo].[users]([id] [int] IDENTITY(1,1) NOT NUL…...

【Vue3】reactive 直接赋值会导致 Vue 无法正确地监听到属性的变化,从而无法触发视图更新
在 Vue 中,响应式数据的监听和视图更新是通过 Vue 的响应式系统实现的。Vue 3 使用了 Proxy 对象来实现响应式,而 Vue 2 使用了 Object.defineProperty 来实现。 当我们使用 reactive 函数创建响应式对象时,Vue 会将对象的每个属性转换为响应…...

服务器出现丢包的原因103.88.35.x
网站主要目的是达到企业和客户紧密联系,提升客户对企业形象的认知度的效果,若租用的服务器不稳定,不仅影响网站的运行,对于网站搜索引擎优化以及用户体验等也有很大的影响。下面是服务器出现丢包不稳定的原因,一起来看…...

pytest study
pytest 测试用例的识别与运行 测试文件:test_*.py 和 *_test.py 以test开头或结尾的文件 测试用例:Test*类包含的所有 test_*的方法(测试类不能带有__init__方法), 不在class中的所有test_*的方法 def func(x):r…...

0基础学习VR全景平台篇 第73篇:VR直播-如何自定义邀请二维码(直播邀请)
自定义直播邀请二维码是自定义直播间邀请卡上显示的二维码,若上传,那么便会替换掉邀请卡上原有的二维码,原二维码为本场直播活动的二维码。 建议上传的尺寸为300px*300px,可选择开启二维码的弹出效果,开启后࿰…...

idea常用技巧/idea常见问题
idea常见问题 idea全局搜索默认只显示100条解决方案 如上图,每次搜索时只显示100条,没法展示全。因版本的不同,配置也有些差异,以下也是经过各种搜索整理出了两个方案来解决这个问题。 方案一: 快捷键Ctrl shift a…...

数据结构---并查集
目录标题 为什么会有并查集并查集的原理模拟实现并查集准备工作构造函数FindRootUnionSetCount 并查集实战题目一:省份数量题目解析题目二:等式方程的可满足性题目解析 为什么会有并查集 这里可以使用生活中的一个例子来带着大家理解并查集,…...

iOS transform rotate总结
研究了一下transform的旋转设置,调了半天还以为是旋转写错了,发现是两个不同的view对象写错了,不管怎么说,还是记录一下旋转相关的操作吧。 参数都是弧度。 以一个图片来举例。 let img UIImageView.init() img.image UIImage…...

关于axios请求java接口中的@RequestParam、@PathVariable及@RequestBody不同接参类型的用法
一、前端传json对象,后端指定接收json对象中的哪个参数。 (1)前端请求 axios({//请求方式method:post,//后端接口路径url:http://127.0.0.1:8080/api/deleteUserById,//注意这里使用的是params,该属性负责把属性名和属性值添加到url后面,一般和get配合使…...

两个点云的重叠部分查找(附open3d python 代码)
方案1 使用 compute_point_cloud_distance: 它计算源点云中的每个点到目标点云中最近点的距离。距离近的点就是重叠点,距离远的点就是非重叠点 方案2 把两个点云变成2个集合set 数据类型,然后求集合的交集就行了,交集就是重叠点…...

PDF文件转换成word软件有哪些?分享两个文件格式转换软件
在日常办公中,我们经常使用各种办公软件,其中PDF和Word是最常见的两种格式。相较于Word文件,PDF文件具有更强的兼容性和安全性,因此我们通常会选择以PDF格式分享文件。然而,如果我们需要提取PDF文件中的部分内容&#…...

redis数据库
目录 1.关系型数据库与非关系型数据库 关系型数据库 非关系型数据库 区别 2.redis 3.安装redis 1.关系型数据库与非关系型数据库 关系型数据库 关系型数据库是一个结构化的数据库,创建在关系模型(二维表格模型)基础上,一般面向…...

SpringMVC-mybatis,SQL语句中误用了desc关键字,导致报错。
17-Jul-2023 21:26:22.295 淇℃伅 [RMI TCP Connection(2)-127.0.0.1] org.apache.catalina.core.ApplicationContext.log 1 Spring WebApplicationInitializers detected on classpath 17-Jul-2023 21:26:22.621 淇℃伅 [RMI TCP Connection(2)-127.0.0.1] org.apache.catalin…...

adb笔记
打开拨号盘 adb shell am start -a android.intent.action.DIAL -d tel:*该命令通过dumpsys window命令获取当前设备的窗口信息,并使用grep mCurrentFocus过滤出包含"mCurrentFocus"关键字的行,从而获取当前活动窗口或应用程序的名称和包名。…...

RocketMQ教程-(5)-功能特性-顺序消息
顺序消息为 Apache RocketMQ 中的高级特性消息,本文为您介绍顺序消息的应用场景、功能原理、使用限制、使用方法和使用建议。 应用场景 在有序事件处理、撮合交易、数据实时增量同步等场景下,异构系统间需要维持强一致的状态同步,上游的事…...

Oracle TNS侦听器远程中毒(CVE-2012-1675)
Oracle TNS侦听器远程中毒(CVE-2012-1675) [oracleorac bin]$ netca -silent -responsefile /home/oracle/netca.rspParsing command line arguments:Parameter "silent" trueParameter "responsefile" /home/oracle/netca.rsp Done parsing command li…...

Springboot+Netty
目录 一、netty入门 二、启动方式 三、netty服务启动类 四、handler链 五、具体业务 六、 线程或者非spring管理的bean中获取spring管理的bean 七、效果 一、netty入门 Netty-导学_哔哩哔哩_bilibili 入门视频量比较大,最主要是了解netty的架构 netty官网&am…...