Databases 15 min read

mybatis-mate: An Enterprise‑Level MyBatis‑Plus Extension for Sharding, Data Auditing, Encryption, and More

This article introduces mybatis-mate, an official MyBatis‑Plus extension that provides enterprise‑grade features such as sharding, multi‑datasource support, data auditing, field encryption, sensitive‑data masking, automatic DDL maintenance, dynamic datasource switching, distributed transaction logging, and fine‑grained data permission control, with detailed usage examples and configuration snippets for Spring Boot projects.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
mybatis-mate: An Enterprise‑Level MyBatis‑Plus Extension for Sharding, Data Auditing, Encryption, and More

Main Features

Dictionary binding

Field encryption

Data masking (sensitive data)

Dynamic table structure maintenance

Data audit records

Data scope (data permission)

Database sharding, dynamic datasource, read/write separation, automatic health‑check and failover

2. Usage

2.1 Dependency Import

Spring Boot automatic dependency:

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-mate-starter</artifactId>
  <version>1.0.8</version>
</dependency>

Annotation package (entity sub‑package):

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-mate-annotation</artifactId>
  <version>1.0.8</version>
</dependency>

2.2 Field Data Binding (Dictionary Write‑Back)

Example: map the user_sex dictionary to the sexText property.

@FieldDict(type = "user_sex", target = "sexText")
private Integer sex;

private String sexText;

Implement IDataDict to provide dictionary data:

@Component
public class DataDict implements IDataDict {
    private Map
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);
    }
}

2.3 Field Encryption

Use @FieldEncrypt to store encrypted values; decryption happens automatically on query. Global and per‑field algorithms are configurable, and custom encryptors can be injected via IEncryptor .

@FieldEncrypt(algorithm = Algorithm.PBEWithMD5AndDES)
private String password;

2.4 Field Sensitive (Data Masking)

Apply @FieldSensitive to mask data according to built‑in or custom strategies.

@FieldSensitive(type = "testStrategy")
private String username;

@FieldSensitive(type = SensitiveType.mobile)
private String mobile;

Custom strategy example:

@Configuration
public class SensitiveStrategyConfig {
    @Bean
    public ISensitiveStrategy sensitiveStrategy() {
        // custom "testStrategy" adds ***test*** suffix
        return new SensitiveStrategy().addStrategy("testStrategy", t -> t + "***test***");
    }
}

2.5 DDL Automatic Maintenance

Supports MySQL and PostgreSQL for automatic schema creation and version‑based SQL execution.

@Component
public class PostgresDdl implements IDdl {
    @Override
    public List
getSqlFiles() {
        return Arrays.asList(
            "db/tag-schema.sql",
            "D:\\db\\tag-data.sql"
        );
    }
}

Dynamic execution example:

ddlScript.run(new StringReader(
    "DELETE FROM user;\n" +
    "INSERT INTO user (id, username, password, sex, email) VALUES (20, 'Duo', '123456', 0, '[email protected]');"
));

2.6 Dynamic Multi‑Datasource Master/Slave Switching

Use @Sharding to switch datasources freely at mapper level.

@Mapper
@Sharding("mysql")
public interface UserMapper extends BaseMapper
{
    @Sharding("postgres")
    Long selectByUsername(String username);
}

Custom sharding strategy example:

@Component
public class MyShardingStrategy extends RandomShardingStrategy {
    @Override
    public void determineDatasourceKey(String group, Invocation invocation, SqlCommandType sqlCommandType) {
        this.changeDatabaseKey(group, sqlCommandType, keys -> chooseKey(keys, invocation));
    }
}

2.7 Distributed Transaction Log Printing

Performance interceptor prints each SQL statement with execution time, supports optional formatting and log‑file writing.

@Slf4j
@Component
@Intercepts({
    @Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),
    @Signature(type = StatementHandler.class, method = "update", args = {Statement.class}),
    @Signature(type = StatementHandler.class, method = "batch", args = {Statement.class})
})
public class PerformanceInterceptor implements Interceptor {
    private long maxTime = 0;
    private boolean format = false;
    private boolean writeInLog = false;
    // ... (implementation omitted for brevity) ...
}

2.8 Data Permission

Define data scope at mapper level with @DataScope and @DataColumn annotations.

@DataScope(type = "test", value = {
    @DataColumn(alias = "u", name = "department_id"),
    @DataColumn(alias = "u", name = "mobile")
})
@Select("select u.* from user u")
List
selectTestList(IPage
page, Long id, @Param("name") String username);

Provide a custom IDataScopeProvider to build the WHERE clause dynamically.

@Bean
public IDataScopeProvider dataScopeProvider() {
    return new AbstractDataScopeProvider() {
        @Override
        protected void setWhere(PlainSelect plainSelect, Object[] args, DataScopeProperty dataScopeProperty) {
            if ("test".equals(dataScopeProperty.getType())) {
                for (DataColumnProperty col : dataScopeProperty.getColumns()) {
                    if ("department_id".equals(col.getName())) {
                        // IN condition for department IDs
                        Set
deptIds = new HashSet<>(Arrays.asList("1","2","3","5"));
                        ItemsList items = new ExpressionList(deptIds.stream().map(StringValue::new).collect(Collectors.toList()));
                        InExpression in = new InExpression(new Column(col.getAliasDotName()), items);
                        plainSelect.setWhere(plainSelect.getWhere() == null ? new Parenthesis(in) : new AndExpression(plainSelect.getWhere(), in));
                    } else if ("mobile".equals(col.getName())) {
                        // LIKE condition for mobile
                        LikeExpression like = new LikeExpression();
                        like.setLeftExpression(new Column(col.getAliasDotName()));
                        like.setRightExpression(new StringValue("%1533%"));
                        plainSelect.setWhere(new AndExpression(plainSelect.getWhere(), like));
                    }
                }
            }
        }
    };
}

Conclusion

The article demonstrates how mybatis-mate can simplify enterprise‑level data handling in Spring Boot applications, covering configuration, code examples, and advanced features such as sharding, encryption, auditing, and fine‑grained permission control.

JavaDatabaseShardingSpring BootMyBatisdata encryptionData Auditing
Java Architect Essentials
Written by

Java Architect Essentials

Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.