【還在使用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 應用開發的理想選擇。
?? 如果你喜歡這篇文章,請點贊支持! ?? 同時歡迎關注我的博客,獲取更多精彩內容!
本文來自博客園,作者:佛祖讓我來巡山,轉載請注明原文鏈接:http://www.rzrgm.cn/sun-10387834/p/19004988

浙公網安備 33010602011771號