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

MyBatis-Flex 完整使用指南

一、环境准备

1. Maven 依赖

xml 复制代码
<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)

yaml 复制代码
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. 实体类配置

java 复制代码
@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 接口

java 复制代码
@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 层实现

java 复制代码
@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)

java 复制代码
// 基础查询
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)

java 复制代码
// 条件更新
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. 分页与聚合

java 复制代码
// 分页查询
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. 事务管理

java 复制代码
// 声明式事务
@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. 高级特性

java 复制代码
// 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. 工具类使用

java 复制代码
// 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 应用开发的理想选择。

相关推荐
救救孩子把4 个月前
MyBatis-Flex、MyBatis-Plus 与 Fluent-Mybatis 的比较分析
java·mybatis·mybatis-plus·mybatis-flex·fluent-mybatis
假客套1 年前
2024 java easyexcel poi word模板填充数据,多个word合成一个word
java·easyexcel·mybatis-flex
假客套1 年前
2024Java springboot mybatis-flex 根据数据表时间开启定时任务
java·开发语言·定时任务·mybatis-flex·启动类
还在忙碌的吴小二1 年前
【比较mybatis、lazy、sqltoy、mybatis-flex、easy-query操作数据】操作批量新增、分页查询(三)
mybatis·easy-query·lazy orm·sqltoy·mybatis-flex