Master Enterprise Data Management with MyBatis‑Mate: Sharding, Encryption & Auditing
This article introduces MyBatis‑Mate, an official MyBatis‑Plus extension that provides enterprise‑grade features such as sharding, data auditing, field encryption, sensitive data masking, dictionary binding, dynamic DDL maintenance, and flexible data‑source switching, complete with usage examples and code snippets.
Today we introduce a MyBatis‑Plus official tool: mybatis‑mate, an enterprise‑level module supporting sharding, data audit, sensitive data filtering (AC algorithm), field encryption, dictionary binding, data permission, automatic DDL generation, and other SQL maintenance features for more agile and elegant data handling.
1. Main Features
Dictionary binding
Field encryption
Data masking
Dynamic table structure maintenance
Data audit records
Data scope (data permission)
Database sharding, dynamic data source, read‑write separation, automatic health‑check switching
2. Usage
2.1 Dependency Import
Spring Boot automatic dependency annotation package
<code><dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-mate-starter</artifactId>
<version>1.0.8</version>
</dependency></code>Annotation package for entity sub‑package usage
<code><dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-mate-annotation</artifactId>
<version>1.0.8</version>
</dependency></code>2.2 Dictionary Binding
Map the "user_sex" dictionary to the "sexText" property
<code>@FieldDict(type = "user_sex", target = "sexText")
private Integer sex;
private String sexText;</code>Implement IDataDict to provide dictionary data source
<code>@Component
public class DataDict implements IDataDict {
private Map<String, String> SEX_MAP = new ConcurrentHashMap<>() {{
put("0", "女");
put("1", "男");
}};
@Override
public String getNameByCode(FieldDict fieldDict, String code) {
System.err.println("字段类型:" + fieldDict.type() + ",编码:" + code);
return SEX_MAP.get(code);
}
}</code>2.3 Field Encryption
Annotate a field with @FieldEncrypt to store encrypted data and automatically decrypt on query. Global and per‑field encryption algorithms can be configured, and custom IEncryptor implementations can be injected.
<code>@FieldEncrypt(algorithm = Algorithm.PBEWithMD5AndDES)
private String password;</code>2.4 Data Masking
Use @FieldSensitive to apply built‑in or custom masking strategies (e.g., name, bank card, phone, email, ID, etc.).
<code>@FieldSensitive(type = "testStrategy")
private String username;
@FieldSensitive(type = SensitiveType.mobile)
private String mobile;</code>Register a custom strategy in the Spring container
<code>@Configuration
public class SensitiveStrategyConfig {
@Bean
public ISensitiveStrategy sensitiveStrategy() {
return new SensitiveStrategy().addStrategy("testStrategy", t -> t + "***test***");
}
}</code>2.5 DDL Automatic Maintenance
Supports MySQL and PostgreSQL for automatic table‑structure updates during version releases.
<code>@Component
public class PostgresDdl implements IDdl {
@Override
public List<String> getSqlFiles() {
return Arrays.asList("db/tag-schema.sql", "D:\\db\\tag-data.sql");
}
}</code>Dynamic execution example
<code>ddlScript.run(new StringReader("DELETE FROM user;\n" +
"INSERT INTO user (id, username, password, sex, email) VALUES\n" +
"(20, 'Duo', '123456', 0, '[email protected]');"));</code>2.6 Dynamic Multi‑DataSource Switching
The @Sharding annotation enables effortless switching between data sources at the mapper level.
<code>@Mapper
@Sharding("mysql")
public interface UserMapper extends BaseMapper<User> {
@Sharding("postgres")
Long selectByUsername(String username);
}</code>Custom sharding strategy example
<code>@Component
public class MyShardingStrategy extends RandomShardingStrategy {
@Override
public void determineDatasourceKey(String group, Invocation invocation, SqlCommandType sqlCommandType) {
this.changeDatabaseKey(group, sqlCommandType, keys -> chooseKey(keys, invocation));
}
}</code>2.7 Data Permission
Add @DataScope on mapper methods to enforce row‑level permissions.
<code>@DataScope(type = "test", value = {
@DataColumn(alias = "u", name = "department_id"),
@DataColumn(alias = "u", name = "mobile")
})
@Select("select u.* from user u")
List<User> selectTestList(IPage<User> page, Long id, @Param("name") String username);
</code>Provider implementation that builds WHERE clauses based on the defined scope
<code>@Bean
public IDataScopeProvider dataScopeProvider() {
return new AbstractDataScopeProvider() {
@Override
protected void setWhere(PlainSelect plainSelect, Object[] args, DataScopeProperty dataScopeProperty) {
if ("test".equals(dataScopeProperty.getType())) {
for (DataColumnProperty dataColumn : dataScopeProperty.getColumns()) {
if ("department_id".equals(dataColumn.getName())) {
Set<String> deptIds = new HashSet<>(Arrays.asList("1","2","3","5"));
ItemsList itemsList = new ExpressionList(deptIds.stream().map(StringValue::new).collect(Collectors.toList()));
InExpression inExpression = new InExpression(new Column(dataColumn.getAliasDotName()), itemsList);
plainSelect.setWhere(plainSelect.getWhere() == null ? new Parenthesis(inExpression) : new AndExpression(plainSelect.getWhere(), inExpression));
} else if ("mobile".equals(dataColumn.getName())) {
LikeExpression like = new LikeExpression();
like.setLeftExpression(new Column(dataColumn.getAliasDotName()));
like.setRightExpression(new StringValue("%1533%"));
plainSelect.setWhere(new AndExpression(plainSelect.getWhere(), like));
}
}
}
}
};
}
</code>Resulting SQL example
<code>SELECT u.* FROM user u
WHERE (u.department_id IN ('1','2','3','5'))
AND u.mobile LIKE '%1533%' LIMIT 1,10</code>3. Conclusion
The author has used MyBatis‑Plus for over four years, noting that it greatly improves development efficiency, unifies code style across the enterprise, and reduces maintenance costs. For enterprises that need advanced data handling, MyBatis‑Mate offers a powerful solution.
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.