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 核心价值:

  1. 极致性能:比传统 ORM 框架快 5-10 倍,适合高并发场景
  2. 轻量灵活:无冗余依赖,功能模块可插拔
  3. 开发效率:复杂 SQL 开发效率提升 3 倍以上
  4. ️ 企业级特性:多租户/字段加密/数据脱敏开箱即用
  5. 智能优化:自动识别数据库方言,智能 SQL 优化

最佳实践场景:

  1. 新项目选型:特别是微服务架构下的新系统
  2. 金融级应用:对数据安全和性能有高要求的系统
  3. 复杂业务系统:需要大量复杂 SQL 的业务(如 ERP、CRM)
  4. 高并发场景:电商、社交等需要处理高并发的系统
  5. 多租户 SaaS:需要灵活租户管理的云应用

迁移建议:

  1. MyBatis → MyBatis-Flex:直接引入,兼容性好
  2. MyBatis-Plus → MyBatis-Flex
    • 保留实体类和 Mapper 接口
    • 逐步替换条件构造器代码
    • 利用 Flex 的兼容模式平滑过渡
  3. 其他 ORM 框架
    • 保留数据库设计
    • 重新生成实体类和 Mapper
    • 业务层逐步重写

终极建议

  • 追求 性能灵活性 → 选择 MyBatis-Flex
  • 需要 稳定简单 CRUD → 选择 MyBatis-Plus
  • 金融/电商 等高性能场景 → 强烈推荐 MyBatis-Flex

MyBatis-Flex 代表了 MyBatis 增强框架的新方向,在保持轻量级的同时提供了企业级功能,是现代化 Java 应用开发的理想选择。

【还在使用MyBatis-Plus?更强大的来了】MyBatis-Flex 完整使用指南的更多相关文章

  1. 比 Navicat 还要好用、功能更强大的工具!

    DBeaver 是一个基于 Java 开发,免费开源的通用数据库管理和开发工具,使用非常友好的 ASL 协议.可以通过官方网站或者 Github 进行下载. 由于 DBeaver 基于 Java 开发 ...

  2. Python的regex模块——更强大的正则表达式引擎

    Python自带了正则表达式引擎(内置的re模块),但是不支持一些高级特性,比如下面这几个: 固化分组    Atomic grouping 占有优先量词    Possessive quantifi ...

  3. 让Docker功能更强大的10个开源工具

    让Docker功能更强大的10个开源工具 更好的管理.Web前端程序.更深入地了解容器应用程序,Docker生态系统正在迅速发展,这还得归功于其充满活力的开源社区. 软件项目的成功常常根据其催生的生态 ...

  4. summerDao-比mybatis更强大无需映射配置的dao工具

    summerDao是summer框架中的一个数据库操作工具,项目地址:http://git.oschina.net/xiwa/summer. 怎么比mybatis更强大,怎么比beetlsql更简单, ...

  5. 【译】AI 让科技公司变得更强大吗

    机器学习可能是当今技术中最重要的基本趋势.由于机器学习的基础是数据 - 大量的数据 - 很常见的是,人们越来越担心已经拥有大量数据的公司会变得更强大.这有一定的道理,但是以相当狭窄的方式,同时ML也看 ...

  6. MyBatis 的真正强大在于它的映射语句 如果有一个独立且完美的数据库映射模式,所有应用程序都可以使用它

    mybatis – MyBatis 3 | Mapper XML 文件 http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html mybatis – My ...

  7. Android内存优化9 内存检测工具3 MAT比Menmery Monitor更强大

    在Android性能优化第(一)篇---基本概念中讲了JAVA的四大引用,讲了一下GCRoot,第二篇Memory Monitor检测内存泄露仅仅说了Menmery Monitor的使用,这篇博客谈一 ...

  8. Android性能优化第(三)篇---MAT比Menmery Monitor更强大

    作者 LooperJing 2016.11.17 16:42* 字数 1687 阅读 1603评论 3喜欢 21 在Android性能优化第(一)篇---基本概念中讲了JAVA的四大引用,讲了一下GC ...

  9. Excel催化剂开源第24波-较VBA更强大的.Net环境的正则表达式

    在VBA上可以调用正则表达式库,从而编写正则表达式自定义函数,这个相信不少VBA开发者已经熟知,但VBA的VBScript正则表达式库毕竟是一个过时的产品,不像.Net那样是与时俱进的,所以两者实现出 ...

  10. 苹果IOS 12将使您的iPhone更安全,并有更强大的黑客保护

    一年一度的IOS刷新正在进行中,苹果已经预览了它,beta测试者已经安装了它,当iPhone在9月份到货时我们其他人应该获得iOS12.虽然软件3-D表情符号和屏幕时间限制等功能在软件到货时可能会受到 ...

随机推荐

  1. UnoCSS原子CSS引擎

    UnoCSS是一款原子化的即时按需 CSS 引擎,其中没有核心实用程序,所有功能都是通过预设提供的.默认情况下UnoCSS应用通过预设来实现相关功能. UnoCSS中文文档: https://www. ...

  2. Nacos源码—8.Nacos升级gRPC分析三

    大纲 7.服务端对服务实例进行健康检查 8.服务下线如何注销注册表和客户端等信息 9.事件驱动架构源码分析 7.服务端对服务实例进行健康检查 (1)服务端对服务实例进行健康检查的设计逻辑 (2)服务端 ...

  3. golang map 和 interface 的一些记录

    golang的map读取是不需要判断key是否存在的,不存在的key会返回默认值. 如果map的value是interface,那么interface是需要先进行类型转换的,非要求类型的转换,得到结果 ...

  4. Seata源码—3.全局事务注解扫描器的初始化

    大纲 1.全局事务注解扫描器继承的父类与实现的接口 2.全局事务注解扫描器的核心变量 3.Spring容器初始化后初始化Seata客户端的源码 4.TM全局事务管理器客户端初始化的源码 5.TM组件的 ...

  5. K8s进阶之外部访问Pod的几种方式

    概述 K8s集群内部的Pod默认是不对外提供访问,只能在集群内部进行访问.这样做是为什么呢? 安全性考虑 Kubernetes设计时遵循最小权限原则,即组件仅获得完成其任务所需的最少权限.直接暴露Po ...

  6. AssemblyResolve巧解未能加载文件或程序集“Newtonsoft.Json, Version=6.0.0.0的问题

    问题:未能加载文件或程序集"Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aee ...

  7. ASP.NET Core Web API中操作方法中的参数来源

    在ASP.NET Core Web API中,有多种方式可以传递参数给操作方法.以下是一些常见的参数传递方式: 路由参数(Route Parameters):参数值从URL的路由中提取. // Rou ...

  8. 使用Files.walk删除文件

    摘要:使用Files.walk删除指定文件名的文件.   使用Files.walk工具,递归判断指定目录中的常规文件路径名是否符合约定名称,如果满足条件就删除. public class DelFil ...

  9. maven pom.xml文件中properties标签介绍

    在properties标签内可以把版本号作为变量进行声明,方便maven依赖标签用${变量名}的形式动态获取版本号.这样做的优点是当版本号发生改变时,仅仅需要更新properties标签中的变量值就行 ...

  10. 【pr】眨眼特效

    来源 这个后半段 步骤 新建一段黑场视频 效果->网格化->边角的两个数值调整很大(4000,4000),现在黑场只剩下一个白色十字架. 效果控件->网格->锚点->第一 ...