【还在使用MyBatis-Plus?更强大的来了】MyBatis-Flex 完整使用指南
MyBatis-Flex 完整使用指南
一、环境准备
1. Maven 依赖
<dependencies>
<!-- MyBatis-Flex 核心依赖 -->
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.8.0</version>
</dependency>
<!-- 数据库驱动(以 MySQL 为例) -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
<!-- Lombok(可选) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
二、完整配置流程
1. 数据源配置 (application.yml)
spring:
datasource:
url: jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC
username: root
password: 123456
driver-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"
2. 实体类配置
@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;
}
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);
}
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();
}
}
三、核心 API 完整使用
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);
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);
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));
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;
});
}
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 注入的安全处理
四、MyBatis-Flex vs MyBatis-Plus 终极对比
特性维度 | MyBatis-Flex | MyBatis-Plus | 优势分析 |
---|---|---|---|
架构设计 | 纯 Java 实现,无第三方依赖 (500KB+) | 依赖 Javassist 等工具 | Flex 更轻量,启动更快 |
多表查询 | 原生支持 JOIN/UNION/子查询 | 需自定义 XML 或使用插件 | Flex 复杂查询开发效率高 5 倍+ |
性能表现 | 基准测试快 5-10 倍 | 中等水平 | Flex 高并发场景优势明显 |
条件构造器 | 链式调用,SQL 风格 | 方法名拼接 | Flex 更直观,学习成本低 |
Lambda 支持 | 全 Lambda 类型推断 | 部分场景需手动指定类型 | Flex 类型安全更好 |
注解功能 | 30+ 种注解覆盖企业级需求 | 基础注解 | Flex 功能更全面 |
字段加密 | 原生支持 AES/RSA 等算法 | 需自定义实现 | Flex 开箱即用 |
多租户 | 注解配置,支持忽略表 | 需插件配置 | Flex 配置更简洁 |
SQL 生成 | 智能识别数据库方言 | 基础分页支持 | Flex 适配性更好 |
代码生成器 | 高度可定制,支持多种模板 | 基础生成功能 | Flex 扩展性更强 |
社区生态 | 快速增长,文档完善 | 成熟稳定,社区庞大 | Plus 更成熟,Flex 更活跃 |
学习曲线 | 陡峭(功能强大) | 平缓(简单易用) | 新项目选 Flex,老项目选 Plus |
五、总结与最佳实践
MyBatis-Flex 核心价值:
- 极致性能:比传统 ORM 框架快 5-10 倍,适合高并发场景
- 轻量灵活:无冗余依赖,功能模块可插拔
- 开发效率:复杂 SQL 开发效率提升 3 倍以上
- ️ 企业级特性:多租户/字段加密/数据脱敏开箱即用
- 智能优化:自动识别数据库方言,智能 SQL 优化
最佳实践场景:
- 新项目选型:特别是微服务架构下的新系统
- 金融级应用:对数据安全和性能有高要求的系统
- 复杂业务系统:需要大量复杂 SQL 的业务(如 ERP、CRM)
- 高并发场景:电商、社交等需要处理高并发的系统
- 多租户 SaaS:需要灵活租户管理的云应用
迁移建议:
- MyBatis → MyBatis-Flex:直接引入,兼容性好
- MyBatis-Plus → MyBatis-Flex:
- 保留实体类和 Mapper 接口
- 逐步替换条件构造器代码
- 利用 Flex 的兼容模式平滑过渡
- 其他 ORM 框架:
- 保留数据库设计
- 重新生成实体类和 Mapper
- 业务层逐步重写
终极建议:
- 追求 性能 和 灵活性 → 选择 MyBatis-Flex
- 需要 稳定 和 简单 CRUD → 选择 MyBatis-Plus
- 金融/电商 等高性能场景 → 强烈推荐 MyBatis-Flex
MyBatis-Flex 代表了 MyBatis 增强框架的新方向,在保持轻量级的同时提供了企业级功能,是现代化 Java 应用开发的理想选择。
【还在使用MyBatis-Plus?更强大的来了】MyBatis-Flex 完整使用指南的更多相关文章
- 比 Navicat 还要好用、功能更强大的工具!
DBeaver 是一个基于 Java 开发,免费开源的通用数据库管理和开发工具,使用非常友好的 ASL 协议.可以通过官方网站或者 Github 进行下载. 由于 DBeaver 基于 Java 开发 ...
- Python的regex模块——更强大的正则表达式引擎
Python自带了正则表达式引擎(内置的re模块),但是不支持一些高级特性,比如下面这几个: 固化分组 Atomic grouping 占有优先量词 Possessive quantifi ...
- 让Docker功能更强大的10个开源工具
让Docker功能更强大的10个开源工具 更好的管理.Web前端程序.更深入地了解容器应用程序,Docker生态系统正在迅速发展,这还得归功于其充满活力的开源社区. 软件项目的成功常常根据其催生的生态 ...
- summerDao-比mybatis更强大无需映射配置的dao工具
summerDao是summer框架中的一个数据库操作工具,项目地址:http://git.oschina.net/xiwa/summer. 怎么比mybatis更强大,怎么比beetlsql更简单, ...
- 【译】AI 让科技公司变得更强大吗
机器学习可能是当今技术中最重要的基本趋势.由于机器学习的基础是数据 - 大量的数据 - 很常见的是,人们越来越担心已经拥有大量数据的公司会变得更强大.这有一定的道理,但是以相当狭窄的方式,同时ML也看 ...
- MyBatis 的真正强大在于它的映射语句 如果有一个独立且完美的数据库映射模式,所有应用程序都可以使用它
mybatis – MyBatis 3 | Mapper XML 文件 http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html mybatis – My ...
- Android内存优化9 内存检测工具3 MAT比Menmery Monitor更强大
在Android性能优化第(一)篇---基本概念中讲了JAVA的四大引用,讲了一下GCRoot,第二篇Memory Monitor检测内存泄露仅仅说了Menmery Monitor的使用,这篇博客谈一 ...
- Android性能优化第(三)篇---MAT比Menmery Monitor更强大
作者 LooperJing 2016.11.17 16:42* 字数 1687 阅读 1603评论 3喜欢 21 在Android性能优化第(一)篇---基本概念中讲了JAVA的四大引用,讲了一下GC ...
- Excel催化剂开源第24波-较VBA更强大的.Net环境的正则表达式
在VBA上可以调用正则表达式库,从而编写正则表达式自定义函数,这个相信不少VBA开发者已经熟知,但VBA的VBScript正则表达式库毕竟是一个过时的产品,不像.Net那样是与时俱进的,所以两者实现出 ...
- 苹果IOS 12将使您的iPhone更安全,并有更强大的黑客保护
一年一度的IOS刷新正在进行中,苹果已经预览了它,beta测试者已经安装了它,当iPhone在9月份到货时我们其他人应该获得iOS12.虽然软件3-D表情符号和屏幕时间限制等功能在软件到货时可能会受到 ...
随机推荐
- 【UEFI】DXE阶段从概念到代码
总述 DXE(Driver Execution Environment)阶段,是执行大部分系统初始化的阶段,也就是说是BIOS发挥作用,初始化整个主板的主战场.在这个阶段我们可以进行大量的驱动工作. ...
- java数组--对象数组的随机赋值及其他
包含考点: 对象数组的随机赋值 浮点数的指定位数 换用思路进行对象数组的某一属性进行排序 现有Book类,定义如下: private String author; private String ISB ...
- 汇编语言笔记——8086&&寻址方式与指令系统
汇编语言中 语句不区分大小写,编译软件会自动识别语句 用户自定义的变量和符号必须区分大小写. 8086 1.寄存器 cpu在访问存储器时,必须指明: 段寄存器:所访问的存储单元属于哪个段 偏移量:相应 ...
- 揭秘!测试开发速看,Mockaroo 如何轻松解决 90% 测试数据难题!
在软件测试领域,模拟生成测试数据一直是至关重要的环节.无论是验证系统功能的准确性,还是测试边界条件下的系统稳定性,都离不开丰富且真实的测试数据. 今天,向大家推荐一款强大的模拟生成测试数据工具 --M ...
- 异步日志监控:FastAPI与MongoDB的高效整合之道
title: 异步日志监控:FastAPI与MongoDB的高效整合之道 date: 2025/05/27 17:49:39 updated: 2025/05/27 17:49:39 author: ...
- Java catch多重异常捕获
摘要:Java中多重异常捕获机制可以更加简洁.有效地处理多个异常,提高了程序的鲁棒性,是编写高质量代码的重要技巧之一. 小编在<浅谈Java异常处理机制>中梳理了异常处理机制,在< ...
- Java四种引用类型回收时机介绍
每种编程语言都有操作内存中元素的方式,例如在 C 和 C++ 里是通过指针,而在 Java 中则是通过"引用"(reference).在 Java 中一切都被视作对象,但是我 ...
- mysql中compact行的存储结构
mysql中行的格式类型包括:Compact.redundant.dynamic.compressed这四种,行和行之间是通过一个单向链表的形式来连接的,而我在实际工作中最常用到的是compact类型 ...
- Seo工具使用与流量数据观察实践(中)
第12章.Seo工具使用与数据观察实践(中) 继上一节的SimilarWeb流量粗分析,我们已经选定了竞品,并且有了一个大致的用户画像和群体,接下来我们就进入细节的关键词和内容的分析. 那么这本节中, ...
- 数栈产品分享:基于StreamWorks构建实时大数据处理平台
数栈是云原生-站式数据中台PaaS,我们在github和gitee上有一个有趣的开源项目:FlinkX,FlinkX是一个基于Flink的批流统一的数据同步工具,既可以采集静态的数据,也可以采集实时变 ...