Why MyBatis-Flex May Outperform MyBatis-Plus: Features, Benchmarks, and Code Samples
This article introduces the MyBatis-Flex ORM framework, highlights its lightweight, flexible, and high‑performance design, compares its features and benchmark results with MyBatis‑Plus, and provides practical code examples for queries, multi‑table joins, partial updates, data masking, multi‑datasource support, and field encryption.
MyBatis-Flex Overview
MyBatis-Flex is an elegant MyBatis enhancement framework that is lightweight (no third‑party dependencies beyond MyBatis), highly flexible with a powerful QueryWrapper , and delivers better performance than traditional MyBatis‑Plus.
Lightweight : only depends on MyBatis itself.
Flexible & Powerful : supports associative queries, multi‑table queries, composite primary keys, logical deletion, optimistic locking, data filling, data masking, etc.
High Performance : benchmarked to be 5‑10× faster than MyBatis‑Plus for single‑record, batch, pagination, and update operations.
It works with most mainstream databases (MySQL, MariaDB, DB2, PostgreSQL, SQLite, DM, KingbaseES, …) and can add new dialects via custom extensions.
The core of MyBatis-Flex is the
QueryWrapper, which handles CRUD, pagination, and can be serialized for RPC transmission, making it suitable for micro‑service architectures.
For a complete e‑commerce demo built with SpringBoot, Vue and uni‑app, see the mall project (60K GitHub stars) .
MyBatis-Flex vs MyBatis-Plus
According to official documentation, MyBatis-Flex offers more features and superior performance compared with MyBatis‑Plus.
Features such as data filling, data masking, and field permissions that require a paid license in MyBatis‑Plus are free in MyBatis-Flex.
Benchmark results show MyBatis-Flex is roughly 5‑10× faster than MyBatis‑Plus for single‑record queries, batch queries, pagination, and updates.
Single‑record query speed: ~5‑10× faster.
10‑record query speed: ~5‑10× faster.
Pagination query speed: ~5‑10× faster.
Data update speed: ~5‑10× faster.
Test source code is available at mybatis‑benchmark .
Basic Query Example
<code>QueryWrapper query = QueryWrapper.create()
.where(EMPLOYEE.LAST_NAME.like(searchWord)) // null condition ignored
.and(EMPLOYEE.GENDER.eq(1))
.and(EMPLOYEE.AGE.gt(24));
List<Employee> employees = employeeMapper.selectListByQuery(query);
</code>Multi‑Table Query Example
<code>QueryWrapper query = QueryWrapper.create()
.select().from(ACCOUNT)
.leftJoin(ARTICLE).on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID))
.where(ACCOUNT.AGE.ge(10));
List<Account> accounts = mapper.selectListByQuery(query);
</code>Partial Field Update Example
<code>Account account = UpdateEntity.of(Account.class);
account.setId(100);
account.setUserName("michael");
account.setAge(18);
account.setBirthday(null);
accountMapper.update(account);
</code>Core Features of MyBatis-Flex
Below are selected core capabilities.
Data Masking
MyBatis-Flex provides the
@ColumnMask()annotation and nine built‑in masking rules (e.g., username, mobile, fixed phone, ID card, car license, address, email, password, bank card).
<code>public class Masks {
public static final String MOBILE = "mobile";
public static final String FIXED_PHONE = "fixed_phone";
public static final String ID_CARD_NUMBER = "id_card_number";
public static final String CHINESE_NAME = "chinese_name";
public static final String ADDRESS = "address";
public static final String EMAIL = "email";
public static final String PASSWORD = "password";
public static final String CAR_LICENSE = "car_license";
public static final String BANK_CARD_NUMBER = "bank_card_number";
// ...
}
</code>Usage example:
<code>@Table("tb_account")
public class Account {
@Id(keyType = KeyType.Auto)
private Long id;
@ColumnMask(Masks.CHINESE_NAME)
private String userName;
@ColumnMask(Masks.EMAIL)
private String email;
}
</code>Multi‑Datasource Support
MyBatis‑Flex natively supports multiple data sources (e.g., Druid, HikariCP, DBCP2, BeeCP) without extra plugins.
<code>mybatis-flex:
datasource:
ds1:
type: druid
url: jdbc:mysql://127.0.0.1:3306/db
username: root
password: 123456
asyncInit: true
ds2:
type: com.your.datasource.type2
url: jdbc:mysql://127.0.0.1:3306/db2
username: root
password: 123456
</code>Switching data sources at runtime:
<code>List<Row> rows = DataSourceKey.use("ds2", () ->
Db.selectAll("tb_account"));
</code>Adding a new data source dynamically:
<code>FlexDataSource flexDataSource = (FlexDataSource) FlexGlobalConfig
.getDefaultConfig().getConfiguration()
.getEnvironment().getDataSource();
HikariDataSource newDataSource = new HikariDataSource();
flexDataSource.addDataSource("newKey", newDataSource);
</code>Field Encryption
Field encryption is implemented via entity listeners that encrypt values before persisting.
<code>public class AccountOnSetListener implements SetListener {
@Override
public Object onSet(Object entity, String property, Object value) {
if (value != null) {
value = encrypt(value);
}
return value;
}
}
@Table(value = "tb_account", onSet = AccountOnSetListener.class)
public class Account {
@Id(keyType = KeyType.Auto)
private Long id;
private String userName;
private String password;
// getters & setters
}
</code>Conclusion
The article compared MyBatis‑Flex with MyBatis‑Plus and introduced several of MyBatis‑Flex's core features, including lightweight design, flexible QueryWrapper, superior performance, data masking, multi‑datasource handling, and field encryption.
For more details, visit the official site https://mybatis-flex.com/ .
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.