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. 信息资源管理综合题之“公钥密码体系中同一个用户拥有的密钥特点 和 如何使用密钥加解密才能保证传输数据的机密性 和 如何身份认证 和 CA的作用”

    一.公钥密码体制在认证技术中是广泛使用的.结合加密和认证技术知识回答以下问题: 1.公钥密码体系中同一个用户拥有的密钥的特点是什么? 2.假设A.B是公钥密码体系的用户,A向B发送数据,A.B之间如何 ...

  2. TVM 安卓环境搭建部署

    安装VULKAN 参考:https://blog.csdn.net/luolinll1212/article/details/113261022 在编译TVM,当config.cmake中将USE_V ...

  3. MSDN I tell you下载方式

    1.复制下载链接 2. 去下载软件粘贴即可 下以百度网盘为例:

  4. 在linux下QImage和QPixmap的内存泄漏和QPixmap线程安全问题

    在linux下QImage和QPixmap的内存泄漏和QPixmap线程安全问题 为什么不在线程里面使用QPixmap(path),而是使用QPixmap::fromImage(QImage(path ...

  5. CentOS7 修改yum源为aliyun

    1,登陆root帐号 2,cd /etc/yum.repo.d 3,mv CentOS-Base.repo CentOS-Base.repo.bak 4,wget http://mirrors.ali ...

  6. 洛谷 P5512 [NOIP1997 提高组] 棋盘问题 加强版

    洛谷 P5512 [NOIP1997 提高组] 棋盘问题 加强版 Problem&Background 可以参考这个 Solution 首先先完成这道题的普通版本P1549 A了那一道题之后, ...

  7. 【2020.11.25提高组模拟】太空漫步(walking) 题解

    [2020.11.25提高组模拟]太空漫步(walking) 题解 题目描述 Do not go gentle into that good night. Old age should burn an ...

  8. Python基础—初识函数(二)

    1.给函数参数增加元信息 写好一个函数,然后想为这个函数的参数增加一些额外的信息,这样的话其他使用者就能清楚的知道这个函数应该怎么使用. 使用函数参数注解是一个很好的办法,它能提示程序员应该怎样正确使 ...

  9. Element-plus组件库的MessageBox 消息弹框组件自定义样式的坑

    一.问题描述: 在使用Element-plus组件库的MessageBox 消息弹框组件时,需要更改该组件的按钮样式,于是根据官网文档: 找到cancel-button-class.confirm-b ...

  10. JWT令牌如何在FastAPI中实现安全又高效的生成与验证?

    title: JWT令牌如何在FastAPI中实现安全又高效的生成与验证? date: 2025/06/10 09:02:35 updated: 2025/06/10 09:02:35 author: ...