【Java开发】 Mybatis-Flex 01:快速入门
Mybatis 作为头部的 ORM 框架,他的增强工具可谓层出不穷,比如出名的 Mybatis-Plus 和 阿里云开源的 Fluent-MyBatis,如今出了一款 Mybatis-Flex ,相比前两款功能更为强大、性能更为强悍,不妨来了解一下。
目录
1 Mybatis-Flex 介绍
2 准备工作
2.1 数据库中创建表及插入数据
2.2 Spring Boot 项目初始化
2.3 添加 Maven 主要依赖
2.4 配置数据源
3 Mybatis-Flex 实践
3.1 编写实体类和 Mapper 接口
3.2 在主启动类添加 @MapperScan 注解
3.3 Test 测试
① 普通查询
② 链式查询
4 MyBatis-Flex/Plus 代码对比
4.1 基础查询
4.2 集合查询
4.3 and(...) 和 or(...)
4.4 多表查询
4.5 部分字段更新
1 Mybatis-Flex 介绍
MyBatis-Flex 是一个优雅的 MyBatis 增强框架,它非常轻量、同时拥有极高的性能与灵活性。
📌 特征
- 轻量:除了 MyBatis,没有任何第三方依赖、没有任何拦截器,在执行的过程中,没有任何的 Sql 解析(Parse)。 这带来了几个好处:极高的性能、极易对代码进行跟踪和调试、把控性更高。
- 灵活:支持 Entity 的增删改查、以及分页查询的同时,MyBatis-Flex 提供了 Db + Row 工具,可以无需实体类对数据库进行增删改查以及分页查询。 与此同时,MyBatis-Flex 内置的 QueryWrapper 可以轻易的帮助我们实现 多表查询、链接查询、子查询 等等常见的 SQL 场景。
- 强大:支持任意关系型数据库,还可以通过方言持续扩展,同时支持 多(复合)主键、逻辑删除、乐观锁配置、数据脱敏、数据审计、 数据填充 等等功能。
简单来说,Mybatis-Flex 相比 Mybatis-Plus 等框架 速度更快、功能更多、代码更简洁~
2 准备工作
官方文档:快速开始 - MyBatis-Flex
以 Spring Boot + Maven + Mysql 项目做演示 👇
2.1 数据库中创建表及插入数据
首先往 Mysql 数据库中添加数据表和对应的数据,脚本如下:
CREATE TABLE IF NOT EXISTS `flex_user`
(`id` INTEGER PRIMARY KEY auto_increment,`user_name` VARCHAR(100),`age` INTEGER,`birthday` DATETIME
);INSERT INTO flex_user(id, user_name, age, birthday)
VALUES (1, '张三', 18, '2020-01-11'),(2, '李四', 19, '2021-03-21');
我使用的是 DBeaver 工具,执行完该语句后效果如下 👇

2.2 Spring Boot 项目初始化
此时需要创建 Spring Boot 项目,并添加 Maven 依赖;此处我通过 IDEA 使用 Spring Initializer 快速初始化一个 Spring Boot 工程。
📌 创建新项目,以下是相关参数:

📌 指定 spring boot 版本和勾选 web 依赖

📌 删除不需要的文件,项目如图 👇

2.3 添加 Maven 主要依赖
往 pom.xml 文件中添加以下依赖,由于本项目是通过 Spring Initializer 搭建,因此已存在 spring-boot-starter-web 和 spring-boot-starter-test 依赖。
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--1.数据库驱动--><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><!-- 数据库连接池组件--><dependency><groupId>com.zaxxer</groupId><artifactId>HikariCP</artifactId></dependency><!--2.lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--3.mybatis-flex--><dependency><groupId>com.mybatis-flex</groupId><artifactId>mybatis-flex-spring-boot-starter</artifactId><version>1.5.4</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>
2.4 配置数据源
在 application.properties 或 application.yml 中配置数据源:
#数据库连接配置
spring.datasource.username=root
spring.datasource.password=root
#mysql5~8 驱动不同driver-class-name 8需要增加时区的配置serverTimezone=UTC,放在url最后
#useSSL=false 安全连接
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
3 Mybatis-Flex 实践
3.1 编写实体类和 Mapper 接口
路径:src/main/java/com/yinyu/flex/pojo/User.java
📌 User 实体类
- 使用 @Table("flex_user") 设置实体类与表名的映射关系
- 使用 @Id(keyType = KeyType.Auto) 标识主键为自增
package com.yinyu.flex.pojo;import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import java.util.Date;@Data
@Table("flex_user")
public class User {@Id(keyType = KeyType.Auto)private Long id;private String userName;private Integer age;private Date birthday;
}
📌 Mapper 接口继承 BaseMapper 接口
路径:src/main/java/com/yinyu/flex/mapper/UserMapper.java
package com.yinyu.flex.mapper;import com.mybatisflex.core.BaseMapper;
import com.yinyu.flex.pojo.User;
import org.springframework.stereotype.Repository;@Repository//代表持久层
public interface UserMapper extends BaseMapper<User> {//所有CRUD操作都编写完成了
}
这部分也可以使用 MyBatis-Flex 的代码生成器来生,功能非常强大的。详情进入:代码生成器章节 了解。
3.2 在主启动类添加 @MapperScan 注解
路径:src/main/java/com/yinyu/flex/MybatisFlexApplication.java
用于扫描 Mapper 文件夹:
package com.yinyu.flex;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan("com.yinyu.flex.mapper")
public class MybatisFlexApplication {public static void main(String[] args) {SpringApplication.run(MybatisFlexApplication.class, args);}}
3.3 Test 测试
路径:src/test/java/com/yinyu/flex/MybatisFlexApplicationTests.java
使用测试类进行测试~
① 普通查询
package com.yinyu.flex;import com.yinyu.flex.mapper.UserMapper;
import com.yinyu.flex.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;@SpringBootTest
class MybatisFlexApplicationTests {//继承了BaseMapper,所有的方法都来自父类,我们也可以编写自己的扩展方法!@Autowiredprivate UserMapper userMapper;@Testvoid contextLoads() {// 查询所有的记录List<User> users = userMapper.selectAll();users.forEach(System.out::println);}
}
输出成功 👇,可以看到完成了查询数据表的操作,展示准确!

② 链式查询
若想使用链式查询还得需要 APT 配置,MyBatis-Flex 使用了 APT(Annotation Processing Tool)技术,在项目编译的时候,会自动根据 Entity/pojo 类定义的字段帮你生成 "USER" 类(可用于链式查询)
通过开发工具构建项目(如下图),或者执行 maven 编译命令: mvn clean package 都可以自动生成。

正常情况下,会在 target 包下生成如下资源 👇

若导入该资源失败,可点击项目目录(注意是项目的根目录),右键 > Maven:
- 先点击 Generate Sources and Update Folders
- 再点击 Reload project

若生成该资源并导入成功,那么此时,可使用链式查询 👇
import static com.yinyu.flex.pojo.table.UserTableDef.USER;
... @Testvoid testWrapper() {// 测试链式查询QueryWrapper queryWrapper = QueryWrapper.create().select().where(USER.AGE.eq(18));User account = userMapper.selectOneByQuery(queryWrapper);System.out.println(account);}
...
总的来说,MyBatis-Flex 的链式查询相比 MyBatis-Plus 多了一步配置环节,目前来看其他步骤类似。
4 MyBatis-Flex/Plus 代码对比
接下来看一下MyBatis-Flex 和 MyBatis-Plus 各部分功能代码的差别,Employee、Account
4.1 基础查询
MyBatis-Flex:
QueryWrapper query = QueryWrapper.create().where(EMPLOYEE.LAST_NAME.like(searchWord)) //条件为null时自动忽略.and(EMPLOYEE.GENDER.eq(1)).and(EMPLOYEE.AGE.gt(24));
List<Employee> employees = employeeMapper.selectListByQuery(query);
MyBatis-Plus:
QueryWrapper<Employee> queryWrapper = Wrappers.query().like(searchWord != null, "last_name", searchWord).eq("gender", 1).gt("age", 24);
List<Employee> employees = employeeMapper.selectList(queryWrapper);//lambda 写法:
LambdaQueryWrapper<Employee> queryWrapper = Wrappers.<Employee>lambdaQuery().like(StringUtils.isNotEmpty(searchWord), Employee::getUserName,"B").eq(Employee::getGender, 1).gt(Employee::getAge, 24);
List<Employee> employees = employeeMapper.selectList(queryWrapper);
4.2 集合查询
MyBatis-Flex:
QueryWrapper query = QueryWrapper.create().select(ACCOUNT.ID,ACCOUNT.USER_NAME,max(ACCOUNT.BIRTHDAY),avg(ACCOUNT.SEX).as("sex_avg"));
List<Employee> employees = employeeMapper.selectListByQuery(query);
MyBatis-Plus:
QueryWrapper<Employee> queryWrapper = Wrappers.query().select("id","user_name","max(birthday)","avg(birthday) as sex_avg");
List<Employee> employees = employeeMapper.selectList(queryWrapper);
缺点:字段硬编码,容易拼错。无法使用 IDE 的字段进行重构,无法使用 IDE 自动提示,发生错误不能及时发现。
4.3 and(...) 和 or(...)
假设我们要构建如下的 SQL 进行查询(需要在 SQL 中添加括号)。
SELECT * FROM tb_account
WHERE id >= 100
AND (sex = 1 OR sex = 2)
OR (age IN (18,19,20) AND user_name LIKE "%michael%" )
MyBatis-Flex:
QueryWrapper query = QueryWrapper.create().where(ACCOUNT.ID.ge(100)).and(ACCOUNT.SEX.eq(1).or(ACCOUNT.SEX.eq(2))).or(ACCOUNT.AGE.in(18, 19, 20).and(ACCOUNT.USER_NAME.like("michael")));
MyBatis-Plus:
QueryWrapper<Employee> query = Wrappers.query().ge("id", 100).and(i -> i.eq("sex", 1).or(x -> x.eq("sex", 2))).or(i -> i.in("age", 18, 19, 20).like("user_name", "michael"));
// or lambda
LambdaQueryWrapper<Employee> query = Wrappers.<Employee>lambdaQuery().ge(Employee::getId, 100).and(i -> i.eq(Employee::getSex, 1).or(x -> x.eq(Employee::getSex, 2))).or(i -> i.in(Employee::getAge, 18, 19, 20).like(Employee::getUserName, "michael"));
4.4 多表查询
📌 情况1
MyBatis-Flex:
QueryWrapper query = QueryWrapper.create().select().from(ACCOUNT).leftJoin(ARTICLE).on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID)).where(ACCOUNT.AGE.ge(10));List<Account> accounts = mapper.selectListByQuery(query);
MyBatis-Plus:不支持
📌 情况2
假设查询的 SQL 如下:
SELECT a.id, a.user_name, b.id AS articleId, b.title
FROM tb_account AS a, tb_article AS b
WHERE a.id = b.account_id
MyBatis-Flex:
QueryWrapper query = new QueryWrapper()
.select(ACCOUNT.ID, ACCOUNT.USER_NAME, ARTICLE.ID.as("articleId"), ARTICLE.TITLE)
.from(ACCOUNT.as("a"), ARTICLE.as("b"))
.where(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID));
MyBatis-Plus:不支持
4.5 部分字段更新
假设一个实体类 Account 中,我们要更新其内容如下:
- userName 为 "michael"
- age 为 "18"
- birthday 为 null
其他字段保持数据库原有内容不变,要求执行的 SQL 如下:
update tb_account
set user_name = "michael", age = 18, birthday = null
where id = 100
MyBatis-Flex 代码如下:
Account account = UpdateEntity.of(Account.class);
account.setId(100); //设置主键
account.setUserName("michael");
account.setAge(18);
account.setBirthday(null);accountMapper.update(account);
MyBatis-Plus 代码如下(或可使用 MyBatis-Plus 的 LambdaUpdateWrapper,但性能没有 UpdateWrapper 好):
UpdateWrapper<Account> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", 100);
updateWrapper.set("user_name", "michael");
updateWrapper.set("age", 18);
updateWrapper.set("birthday", null);accountMapper.update(null, updateWrapper);
如上,MyBatis-Flex 在代码编写来说还是有些优势。
相关文章:
【Java开发】 Mybatis-Flex 01:快速入门
Mybatis 作为头部的 ORM 框架,他的增强工具可谓层出不穷,比如出名的 Mybatis-Plus 和 阿里云开源的 Fluent-MyBatis,如今出了一款 Mybatis-Flex ,相比前两款功能更为强大、性能更为强悍,不妨来了解一下。 目录 1 Myba…...
企业级业务架构学习笔记<二>
一.业务架构基础 业务架构的定义 以实现企业战略为目标,构建企业整体业务能力规划并将其传导给技术实现端的结构化企业能力分析方法 (业务架构可以从企业战略触发,按照企业战略设计业务及业务过程,业务过程时需要业务能力支撑的࿰…...
Minio在windows环境配置https访问
minio启动后,默认访问方式为http,但是有的时候我们的访问场景必须是https,浏览器有的会默认以https进行访问,这个时候就需要我们进行配置上的调整,将minio从http访问升级到https。而查看minio的官方文档,并…...
安装JDK环境(Windows+Linux双教程)
今日一语:今天的事情不去做,到了明天就成了麻烦,到了下个月就成了隐患,到了明年只剩下悔恨和惋惜 Linux 从Oracle网站下载linux的rpm包java -version 查询java环境是否已经安装 如果已经安装,可以选择卸载重装或者直接…...
SVG图标,SVG symbols,SVG use标签
SVG图标,SVG symbols 项目中图标的使用,趋势是使用svg作图标的,优点如下 兼容现有图片能力前提还支持矢量 可读性好,有利于SEO与无障碍 在性能和维护性方面也比iconfont要强很多 怎么在项目中优雅的使用svg图标,下面…...
常用css 笔记
0、定义变量 :root { --primary-color: #007bff;} .button { background-color: var(--primary-color);} 1、水平垂直居中 div {width: 100px;height: 100px;position: absolute;top: 0;right: 0;bottom: 0;left: 0;margin: auto; }父级控制子集居中 .parent {display: fle…...
git的ssh方式对接码云
一、环境准备: 1、git下载,360管家或是百度。 2、vs2022,百度下载。 二、配置git: 1、打开准备存放文件的文件夹,右键,选择“Git Bash here”,弹出命令窗口, 输入:ss…...
Golang之路---02 基础语法——变量
Golang变量 变量的声明 声明变量的一般形式是使用 var 关键字 Go 语言是静态类型语言,编译时,编译器会检查变量的类型,所以要求所有的变量都要有明确的类型。 1 :一个变量单行声明 语法格式: var name type var是关…...
Webpack5 DefinePlugin的作用
在Webpack 5中,DefinePlugin是一个插件,用于创建全局常量,这些常量可以在编译过程中被引用。它的作用是允许开发人员在代码中定义全局变量,这些变量在构建过程中将被替换为其对应的值。 DefinePlugin并不是必须的,但它…...
Verilog语法学习——LV7_求两个数的差值
LV7_求两个数的差值 题目来源于牛客网 [牛客网在线编程_Verilog篇_Verilog快速入门 (nowcoder.com)](https://www.nowcoder.com/exam/oj?page1&tabVerilog篇&topicId301) 题目 描述 根据输入信号a,b的大小关系,求解两个数的差值:输入信号a,b…...
C#匿名函数,lambda表达式笔记
一.匿名函数 匿名函数是一种定义时不起函数名的技术,因此无法直接调用,通常用来赋值给委托后被委托调用。在匿名方法中您不需要指定返回类型,它是从方法主体内的 return 语句推断的 它的语法形式为:delegate (input-parameters)…...
【图论】LCA(倍增)
一.LCA介绍 LCA通常指的是“最近共同祖先”(Lowest Common Ancestor)。LCA是一种用于解决树或图结构中两个节点的最低共同祖先的问题的算法。 在树结构中,LCA是指两个节点的最近层级的共同祖先节点。例如,考虑一棵树,…...
QT 使用串口
目录 1.1.1 添加库,添加类 1.1.2 定义串口 1.1.3 搜索串口 1.1.4 设置和打开串口 1.1.5 读取数据 1.1.6 发送数据 1.1.7 关闭串口 1.1.1 添加库,添加类 首先,QT5 是自带 QSerialPort(Qt5 封装的串口类)这个类的,使用时…...
GitHub上怎么寻找项目?
前言 下面由我精心整理的关于github项目资源搜索的一些方法,这些方法可以帮助你更快更精确的搜寻到你需要的符合你要求的项目。 写文章不易,如果这一篇问文章对你有帮助,求点赞求收藏~ 好,下面我们直接进入正题——> 首先我…...
如何快速用Go获取短信验证码
要用Go获取短信验证码,通常需要连接到一个短信服务提供商的API,并通过该API发送请求来获取验证码。由于不同的短信服务提供商可能具有不同的API和授权方式,我将以一个简单的示例介绍如何使用Go语言来获取短信验证码。 在这个示例中࿰…...
详解Mybatis查询之resultType返回值类型问题【4种情况】
编译软件:IntelliJ IDEA 2019.2.4 x64 操作系统:win10 x64 位 家庭版 Maven版本:apache-maven-3.6.3 Mybatis版本:3.5.6 文章目录 引言一、查询单行数据返回单个对象二、查询多行数据返回对象的集合三、 查询单行数据返回Map[Key,…...
Python-Python基础综合案例:数据可视化 - 折线图可视化
版本说明 当前版本号[20230729]。 版本修改说明20230729初版 目录 文章目录 版本说明目录知识总览图Python基础综合案例:数据可视化 - 折线图可视化json数据格式什么是jsonjson有什么用json格式数据转化Python数据和Json数据的相互转化 pyecharts模块介绍概况如何…...
CSS盒子模型(HTML元素布局)
CSS盒子模型是一种用于描述HTML元素布局的模型,它将每个元素看作是一个矩形的盒子,每个盒子由内容、内边距、边框和外边距组成。 盒子模型包括以下几个部分: 内容区域(Content) 内容区域是盒子中实际显示内容的部分&am…...
PostgreSQL-Centos7源码安装
卸载服务器上的pg13 本来是想删除原来的postgis重新源码安装就行,但是yum安装的PostgreSQL不能直接使用,会提示以下问题: 之前服务是用yum安装的,现在需要删除 -- 删除数据的postgis插件 drop extension postgis; drop extension postgis cascade;删除相关安装包 # 查询…...
QTday2信号和槽
点击登录按钮,关闭Widget登录窗口,打开QQList窗口 widget.cpp #include "widget.h"void my_setupUI(Widget *w);Widget::Widget(QWidget *parent): QWidget(parent) {my_setupUI(this); }Widget::~Widget() { }void Widget::login_slots() {//fixemit jump_signal(…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
