当前位置: 首页 > news >正文

Mybatis增强版MyBatis-Flex简介

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

功能或特点MyBatis-FlexMyBatis-PlusFluent-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增强版&#xff1a;Mybatis-Plus(使用的最多&#xff0c;老牌Mybatis增强框架&#xff0c;2016年开源)、Fluent-MyBatis(阿里云开发的Mybatis增强框架&#xff0c;来自阿里云.云效产品团队)、Mybatis-Flex。 Flex英文单词意思是灵活&#xff0c;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项目&#xff0c;在启动类上添加注解SpringBootApplication &#xff0c;然后引入要自动注入的组件依赖&#xff0c;然后现application.properties中加上相应配置就可以自动注入这个组件&#xff0c;那么下面看看自动注入组件是如何实现的 一、S…...

短视频矩阵系统源码---开发技术源码能力

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

可观测之调用链Skywalking

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

linux上适用的反汇编调试软件(对标od)

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

基于高斯混合模型聚类的风电场短期功率预测方法(Pythonmatlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 2.1 Python 2.2 Matlab &#x1f389;3 参考文献 &#x1f308;4 Matlab代码、数据、文章讲解 &#x1f4a5;1 概述 文献来源&#xff1a; 摘要&#xff1a;对任意来流条件下的风电场发电功率进行准确预测,是提高电网对风电…...

【深入了解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 中&#xff0c;你可以通过实现 UIScrollViewDelegate 的方法来检测滑动结束事件。具体来说&#xff0c;你可以实现以下方法&#xff1a; func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {if !decelerat…...

html学习2(css、图像)

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

微服务探索之路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 数据导出

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

SSIS对SQL Server向Mysql数据转发表数据 (二)

1、在SQL Server数据库创建一个数据库表&#xff1a;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 中&#xff0c;响应式数据的监听和视图更新是通过 Vue 的响应式系统实现的。Vue 3 使用了 Proxy 对象来实现响应式&#xff0c;而 Vue 2 使用了 Object.defineProperty 来实现。 当我们使用 reactive 函数创建响应式对象时&#xff0c;Vue 会将对象的每个属性转换为响应…...

服务器出现丢包的原因103.88.35.x

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

pytest study

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

0基础学习VR全景平台篇 第73篇:VR直播-如何自定义邀请二维码(直播邀请)

自定义直播邀请二维码是自定义直播间邀请卡上显示的二维码&#xff0c;若上传&#xff0c;那么便会替换掉邀请卡上原有的二维码&#xff0c;原二维码为本场直播活动的二维码。 建议上传的尺寸为300px*300px&#xff0c;可选择开启二维码的弹出效果&#xff0c;开启后&#xff0…...

idea常用技巧/idea常见问题

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

数据结构---并查集

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

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...