MyBatis Flex 讲解使用

news/2025/11/22 18:59:46/文章来源:https://www.cnblogs.com/jingzh/p/19258370

目录
  • 1 MyBatis Flex
    • 1.1 简介
    • 1.2 简单操作
      • 1.2.1 配置
        • 1.2.1.1 pom.xml
        • 1.2.1.2 yml配置
      • 1.2.2 生成代码
      • 1.2.3 业务类
        • 1.2.3.1 实体
        • 1.2.3.2 实体脱敏
        • 1.2.3.3 Mapper接口
        • 1.2.3.4 Service层
    • 1.3 MyBatis-Flex 核心 API
      • 1.3.1 条件构造器(QueryWrapper)
      • 1.3.2 更新操作(UpdateWrapper)
      • 1.3.3 分页与聚合
      • 1.3.4 事务管理
      • 1.3.5 高级特性

1 MyBatis Flex

1.1 简介

MyBatis-Flex 是一个在 MyBatis 基础上深度增强的框架,专为解决 Java 开发中数据库操作的复杂性而设计。它不仅保留了 MyBatis 原生的灵活性,可以自由编写 SQL 语句,同时又引入了一系列强大的特性,大大简化了开发流程。
MyBatis-Flex 官网
教程学习地址:https://mybatis-flex.com/zh/intro/getting-started.html

与其他 ORM 框架相比,MyBatis-Flex 具有显著的优势。它非常轻量,除了 MyBatis 之外,没有任何第三方依赖,这不仅减少了项目的依赖复杂度,还提高了系统的稳定性和自主性。在性能方面,MyBatis-Flex 表现卓越,其独特的架构设计,在 SQL 执行过程中没有任何 SQL 解析操作,从而带来了指数级的性能增长 ,查询单条数据和查询 10 条数据的速度,大概是 MyBatis-Plus 的 5-10 倍。

和MyBatis-Plus 与 Fluent-Mybatis 对比:

功能或特点 MyBatis-Flex MyBatis-Plus Fluent-Mybatis
对 entity 的基本增删改查
分页查询
分页查询之总量缓存
多表查询: from 多张表
多表查询: left join、inner join 等等
多表查询: union,union all
单主键配置
多种 id 生成策略
支持多主键、复合主键
字段的 typeHandler 配置
除了 Mybatis,无其他第三方依赖(更轻量)
QueryWrapper 是否支持在微服务项目下进行 RPC 传输 未知
逻辑删除
乐观锁
SQL 审计
数据填充 ✔️ (收费)
数据脱敏 ✔️ (收费)
字段权限 ✔️ (收费)
字段加密 ✔️ (收费)
字典回写 ✔️ (收费)
Db + Row
Entity 监听
多数据源支持 ✅(不支持非Spring项目)
多数据源是否支持 Spring 的事务管理,比如 @Transactional 和 TransactionTemplate 等
多数据源是否支持 "非Spring" 项目
多租户
动态表名
动态 Schema

1.2 简单操作

1.2.1 配置

1.2.1.1 pom.xml

SpringBoot v2.x 的场景下依赖

<!-- MyBatis-Flex 核心依赖 -->
<dependency><groupId>com.mybatis-flex</groupId><artifactId>mybatis-flex-spring-boot-starter</artifactId><version>1.11.4</version>
</dependency><!-- 数据库驱动(以 MySQL 为例) -->
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.33</version>
</dependency><!-- 用于生成代码-->
<dependency><groupId>com.mybatis-flex</groupId><artifactId>mybatis-flex-codegen</artifactId><version>1.11.4</version>
</dependency>
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.23</version>
</dependency>

SpringBoot v3.x,需要使用如下依赖:

<dependency><groupId>com.mybatis-flex</groupId><artifactId>mybatis-flex-spring-boot3-starter</artifactId><version>1.11.3</version>
</dependency>

1.2.1.2 yml配置

在application.yml文件中配置数据源

spring:datasource:url: jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTCusername: xxxxpassword: xxxxdriver-class-name: com.mysql.cj.jdbc.Driver# MyBatis-Flex 高级配置
mybatis-flex:# 是否打印 SQL(开发环境建议开启)print-sql: true# 全局配置global-config:# 逻辑删除配置logic-delete:logic-delete-value: 1  # 已删除值logic-not-delete-value: 0 # 未删除值# 多租户配置tenant-config:ignore-tables: sys_config, sys_log # 忽略租户过滤的表# 字段安全类型(脱敏/加密)column-security:# 全局加密密钥(可覆盖)aes-key: "my-secret-key-123"

1.2.2 生成代码

public static void main(String[] args) {//配置数据源DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8");dataSource.setUsername("root");dataSource.setPassword("root");GlobalConfig globalConfig = createGlobalConfigUseStyle();//通过 datasource 和 globalConfig 创建代码生成器Generator generator = new Generator(dataSource, globalConfig);//生成代码generator.generate();}public static GlobalConfig createGlobalConfigUseStyle() {//创建配置内容GlobalConfig globalConfig = new GlobalConfig();String projectPath = AutoGen.class.getResource("/").getPath();String sourceDir = projectPath.substring(0, projectPath.indexOf("/target/")) ;globalConfig.setSourceDir(sourceDir);//设置根包globalConfig.getPackageConfig().setBasePackage("com.test").setMapperXmlPath(sourceDir+"/com/test/mapper");//设置表前缀和只生成哪些表,setGenerateTable 未配置时,生成所有表globalConfig.getStrategyConfig().setGenerateTable("user");//设置生成 entity 并启用 LombokglobalConfig.enableEntity().setWithLombok(true).setJdkVersion(17).setClassSuffix("Entity");//设置生成相关类及文件globalConfig.enableMapper();globalConfig.enableMapperXml();globalConfig.enableService();globalConfig.enableServiceImpl();globalConfig.enableController();//可以单独配置某个列/*ColumnConfig columnConfig = new ColumnConfig();columnConfig.setColumnName("tenant_id");columnConfig.setLarge(true);columnConfig.setVersion(true);globalConfig.getStrategyConfig().setColumnConfig("tb_account", columnConfig);*/return globalConfig;}

1.2.3 业务类

1.2.3.1 实体

@Table("tb_account")
@Data
public class Account {@Id(keyType = KeyType.Auto)private Long id;@Column("user_name")private String userName;private Integer age;@Column(onInsertValue = "now()")private LocalDateTime createTime;@Column(onUpdateValue = "now()")private LocalDateTime updateTime;// 逻辑删除字段(0:正常,1:删除)@Column(logicDelete = true)private Integer isDeleted;// 多租户字段@Column(tenantId = true)private Long tenantId;// 加密字段(手机号)@Column(cryptoType = CryptoType.AES)private String mobile;// 脱敏字段(银行卡号)@Column(maskType = MaskType.BANK_CARD)private String bankCard;// 乐观锁字段@Column(version = true)private Integer version;
}

@ColumnMaskMyBatis-Flex 提供的内置脱敏注解,目前已经提供了9种脱敏规则,具体:手机号脱敏、固定电话脱敏、身份证号脱敏、车牌号脱敏、地址脱敏、邮件脱敏、密码脱敏、银行卡号脱敏

1.2.3.2 实体脱敏

Mybaits-Flex 内置的9种脱敏规则无法满足要求时,我们还可以自定义脱敏规则,其步骤如下:
通过 MaskManager 注册新的脱敏规则:

MaskManager.registerMaskProcessor("自定义规则名称", data -> {return data;})

使用自定义的脱敏规则

@Table("tb_account")
public class Account {@Id(keyType = KeyType.Auto)private Long id;@ColumnMask("自定义规则名称")private String userName;
}

1.2.3.3 Mapper接口

@Mapper
public interface AccountMapper extends BaseMapper<Account> {// 自定义SQL方法示例@Select("SELECT * FROM tb_account WHERE age > #{minAge}")List<Account> selectByMinAge(@Param("minAge") int minAge);
}

1.2.3.4 Service层

@Service
public class AccountService extends ServiceImpl<AccountMapper, Account> {// 自定义业务方法public List<Account> findAdults() {return queryChain().select(Account::getId, Account::getUserName).where(Account::getAge).ge(18).list();}
}

1.3 MyBatis-Flex 核心 API

1.3.1 条件构造器(QueryWrapper)

// 基础查询
QueryWrapper query = QueryWrapper.create().select(ACCOUNT.ID, ACCOUNT.USER_NAME, ACCOUNT.AGE).from(ACCOUNT).where(ACCOUNT.AGE.between(18, 60)).and(ACCOUNT.USER_NAME.like("张%")).orderBy(ACCOUNT.AGE.desc(), ACCOUNT.ID.asc()).limit(10);// 联表查询(带别名)
QueryWrapper query = QueryWrapper.create().select(ACCOUNT.ID, ORDER.ORDER_NO, ORDER.AMOUNT).from(ACCOUNT.as("a")).leftJoin(ORDER).as("o").on(ACCOUNT.ID.eq(ORDER.ACCOUNT_ID)).where(ORDER.CREATE_TIME.ge(LocalDate.now().minusMonths(1))).groupBy(ACCOUNT.ID).having(sum(ORDER.AMOUNT).gt(10000));// 子查询
QueryWrapper subQuery = QueryWrapper.create().select(ORDER.ACCOUNT_ID).from(ORDER).where(ORDER.STATUS.eq(1));QueryWrapper mainQuery = QueryWrapper.create().select().from(ACCOUNT).where(ACCOUNT.ID.in(subQuery)).and(ACCOUNT.TENANT_ID.eq(123));// Lambda 表达式
LambdaQueryWrapper<Account> lambdaQuery = LambdaQueryWrapper.create().select(Account::getId, Account::getUserName).eq(Account::getAge, 25).likeRight(Account::getUserName, "张").orderByDesc(Account::getCreateTime);

1.3.2 更新操作(UpdateWrapper)

// 条件更新
UpdateWrapper update = UpdateWrapper.create().set(ACCOUNT.AGE, ACCOUNT.AGE.add(1)).set(ACCOUNT.UPDATE_TIME, LocalDateTime.now()).where(ACCOUNT.LAST_LOGIN_TIME.lt(LocalDate.now().minusYears(1)));// 实体更新
Account account = new Account();
account.setStatus(2);
UpdateWrapper update = UpdateWrapper.of(account).where(ACCOUNT.STATUS.eq(1).and(ACCOUNT.AGE.lt(18)));// Lambda 更新
LambdaUpdateWrapper<Account> lambdaUpdate = LambdaUpdateWrapper.create().set(Account::getAge, 30).set(Account::getUpdateTime, LocalDateTime.now()).eq(Account::getId, 1001);

1.3.3 分页与聚合

// 分页查询
Page<Account> page = Page.of(1, 20); // 第1页,每页20条
QueryWrapper query = QueryWrapper.create().where(ACCOUNT.AGE.ge(18)).orderBy(ACCOUNT.CREATE_TIME.desc());Page<Account> result = mapper.paginate(page, query);// 分页结果处理
List<Account> records = result.getRecords();
long total = result.getTotalRow();
long totalPages = result.getTotalPage();// 聚合查询
QueryWrapper aggQuery = QueryWrapper.create().select(ACCOUNT.DEPT_ID, count().as("emp_count"),avg(ACCOUNT.SALARY).as("avg_salary"),max(ACCOUNT.SALARY).as("max_salary")).groupBy(ACCOUNT.DEPT_ID).having(avg(ACCOUNT.SALARY).gt(10000));

1.3.4 事务管理

// 声明式事务
@Transactional(rollbackFor = Exception.class)
public void transferMoney(Long fromId, Long toId, BigDecimal amount) {// 扣减转出账户UpdateWrapper deduct = UpdateWrapper.create().setRaw(ACCOUNT.BALANCE, "balance - ?", amount).where(ACCOUNT.ID.eq(fromId));accountMapper.updateByQuery(deduct);// 增加转入账户UpdateWrapper add = UpdateWrapper.create().setRaw(ACCOUNT.BALANCE, "balance + ?", amount).where(ACCOUNT.ID.eq(toId));accountMapper.updateByQuery(add);// 记录交易流水transactionService.logTransfer(fromId, toId, amount);
}// 编程式事务
public void batchImport(List<Account> accounts) {Transaction.tx(() -> {for (Account account : accounts) {if (account.getAge() < 18) {throw new RuntimeException("未成年账户禁止导入");}accountMapper.insert(account);}return true;});
}

1.3.5 高级特性

// 1. 逻辑删除(自动添加条件)
accountMapper.deleteById(1L); // → UPDATE SET is_deleted=1 WHERE id=1// 2. 多租户过滤(自动添加租户ID条件)
List<Account> list = accountMapper.selectAll(); 
// → SELECT * FROM tb_account WHERE tenant_id=当前租户ID// 3. 字段加密/解密(自动处理)
Account account = accountMapper.selectOneById(1L);
System.out.println(account.getMobile()); // 自动解密 → 13800138000// 4. 数据脱敏
Account account = accountMapper.selectOneById(1L);
System.out.println(account.getBankCard()); // → 622202******1234// 5. 乐观锁更新
Account account = accountMapper.selectOneById(1L);
account.setBalance(account.getBalance() + 100);
accountMapper.update(account); 
// → UPDATE ... WHERE id=1 AND version=旧版本
6、工具类使用// Db 工具类快速操作
Db.insert("account", "id,user_name,age", 1001, "张三", 30);
Db.updateById("account", "age", 31, 1001);
List<Account> list = Db.selectAllByCondition(Account.class, "age > ?", 18);// 批量操作
List<Account> accounts = ...;
Db.executeBatch(accounts, 1000, (mapper, account) -> {mapper.insert(account);
});// SQL 工具
String inSql = SqlUtil.buildInCondition("id", Arrays.asList(1,2,3));
// → id IN (1,2,3)String safeSql = SqlUtil.escapeSql("SELECT * FROM user WHERE name='admin' OR 1=1");
// → 防止 SQL 注入的安全处理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/973340.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Catalog

东西有点杂,稍微整理一下。 Algorithm Introduction【老】Splay 浅谈

NCHU_Blog1_刘素萍_单部电梯调度程序

一、前言 经过前几周的课堂讲解与视频学习,已初步掌握 Java 的基础用法。相较于 C 语言,Java 最核心的差异在于引入了 “类” 的概念 —— 课堂上老师对此概念花了大力气进行了重点讲解。在PTA完成了前三次 Java 迭代…

同花顺通达信常用颜色图标

1)Color 自定义色格式为color+“Rrggbb”:Rr、Gg、Bb表示红蓝色、绿色和蓝色 2)Colorblack 黑色画黑色 3)Colorblue 蓝色画蓝色 4)Colorgreen 绿色画绿色 5)Colorcyan 青色画青色 6)Colorred 红色画红色 7)Col…

hive sql开发难不难

Hive SQL开发的难度因人而异,但总体来说,对于熟悉SQL的开发者来说,Hive SQL的学习曲线相对平缓,因为Hive SQL语法与标准SQL相似。以下是对Hive SQL开发难度、入门建议以及是否适合初学者的分析: Hive SQL开发难度…

数学的大厦(五):除法、有理数、等价关系

在整数这个崭新的世界里,乘法是畅通无阻的。但它的逆运算——除法,又成了新的不可能任务。6 / 3 = 2,没问题,结果还是个整数。但 3 / 6 呢?2 / 3 呢?1 / 2 呢?在整数的世界里,没有它们的容身之处。 是时候再次…

KingbaseES电科金仓数据库SQL调优 - 实践

KingbaseES电科金仓数据库SQL调优 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "M…

一种自定义二维码的加码、解码、识别和绘制算法的逆向和重构

1. 珊瑚码定义 这种二维码是在某金融机构打码机上使用的一种形似二维码但是又不遵循二维码标准的图形码。其形状在正方形四个角上有回型图案,中间为一个大型回字图案。 在生物学上来看比较像簇生珊瑚,故暂时命名为珊…

ddddocr: 安装ddddocr

一,项目官方地址 https://github.com/sml2h3/ddddocr 二,安装 $ pip install ddddocr 三,代码: import base64 from ddddocr import DdddOcrocr = DdddOcr()img = "data:image/png;base64,iVBORw0KGgoAAAANSU…

电梯调度总结Blog

一、前言 三次电梯调度大作业,迭代需求升级,任务逐渐增加需求,难度逐渐增加,主要是培养我们面向对象编程的思想、算法设计、代码重构与问题排查。 知识点包括类与对象的定义与使用、构造方法、getter/setter 方法封…

浅谈最近星某克被指追杀式营销的技术实现方式和商业价值利弊

本文从技术架构角度剖析星巴克App"追杀式"营销现象,探讨位置感知技术实现原理、数据隐私边界与用户体验权衡,强调技术创新应尊重用户隐私,在商业价值与用户权益间找到合理平衡。关注我,获取更多企业级架…

深入解析:职场发展—如何避雷垃圾公司

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

ssh隧道

有些服务器只开放了22端口给ssh连接, 我们在服务器A上部署的其他应用使用其他端口(如5601)就无法访问,这时候我们可以找一台中间服务器B,这台服务器B要稳定而且能和服务器A、我们的电脑通信(这台我用的windows服…

AI搜索驱动的品牌传播变革:品牌如何在“被搜索”转向“被理解”的浪潮中重构增长力 - 教程

AI搜索驱动的品牌传播变革:品牌如何在“被搜索”转向“被理解”的浪潮中重构增长力 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !import…

数据库常用编码和压缩算法介绍

数据库常用编码和压缩算法介绍在设计一个优秀的数据库时,存储空间、性能以及资源占用无疑是必须深入考虑的关键因素。这些因素直接关联到数据库的效率、成本以及用户的体验。这里面,编码与压缩也是至关重要的一环。 …

onenote复制纯文本的方法

onenote在复制文本到其他地方进行粘贴后,经常会变成图片,以下是解决办法: 方法一: 1. 使用win + Q 或者 win + S 复制后再粘贴 方法二: 2. 复制到word中 方法三: 3. 上使用Ditto剪切板增强软件3.1 复制后 使用Al…

hive sql开发有啥优势

Hive SQL开发相较于传统的SQL开发,具有以下显著优势:灵活的数据模型:Hive支持非结构化和半结构化数据,如文本文件、图像、视频等。这使得它能够处理更多种类的数据,满足更广泛的业务需求。 大规模数据处理能力:H…

hive sql开发怎样避免错误

在Hive SQL开发中,避免错误的方法有很多。以下是一些建议:熟悉Hive SQL语法:确保你对Hive SQL的语法有深入的了解。这将帮助你避免编写错误的查询语句。 使用正确的数据类型:在定义表和列时,确保使用正确的数据类…

完整教程:C语言标准库完全指南

完整教程:C语言标准库完全指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&quo…

fedora43使用incus启动虚拟机报错: qemu-system-x86_64: Unknown audio driver spice

操作系统版本: Fedora 43 (Server Edition) linux内核版本: 6.17.1-300.fc43.x86_64 incus版本: 6.18 qemu-system-x86_64版本: QEMU emulator version 10.1.2 (qemu-10.1.2-1.fc43) 问了chatgpt和结合github上相关iss…

hive sql开发常见错误是啥

Hive SQL开发中常见的错误有很多种,以下是一些例子:语法错误:这是最常见的错误类型,可能是由于拼写错误、缺少必要的符号或者使用了错误的命令。例如,如果你忘记了在SELECT语句后加上分号,就会收到一个语法错误。…