How to Implement Multi‑Tenant Architecture in MyBatis‑Plus: A Step‑by‑Step Guide
This article explains the concept of multi‑tenant architecture, compares three data isolation strategies, and provides a complete MyBatis‑Plus configuration with code examples to automatically add tenant IDs, including how to filter specific SQL statements, helping developers build cost‑effective SaaS back‑ends.
1. Introduction
Multi‑tenant is a software architecture technique where a single system serves multiple users while ensuring data isolation between tenants.
For example, an H5 application deployed in different hospital apps passes a tenant ID (hospital identifier) with each request so that data can be separated per hospital.
Data isolation can be achieved in three ways:
Independent databases: each tenant has its own database, offering the highest isolation and security but higher cost.
Shared database with isolated schemas: tenants share a database but have separate schemas (users).
Shared database with shared schema: tenants share the same tables and add a tenant_id column, which is the cheapest but provides the lowest isolation.
2. Implementation
We adopt the third approach—shared database and shared schema—because it minimizes server costs at the expense of higher development effort.
MyBatis‑Plus provides a multi‑tenant solution based on the pagination plugin. The configuration code is as follows:
@Configuration
public class MyBatisPlusConfig {
/**
* Pagination interceptor
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// Create SQL parser list
List<ISqlParser> sqlParserList = new ArrayList<>();
// Create tenant SQL parser
TenantSqlParser tenantSqlParser = new TenantSqlParser();
// Set tenant handler
tenantSqlParser.setTenantHandler(new TenantHandler() {
@Override
public Expression getTenantId() {
// Set current tenant ID (e.g., from cookie or cache)
return new StringValue("jiannan");
}
@Override
public String getTenantIdColumn() {
// Column name for tenant ID in the database
return "tenant_id";
}
@Override
public boolean doTableFilter(String tableName) {
// Whether to filter a specific table
return false;
}
});
sqlParserList.add(tenantSqlParser);
paginationInterceptor.setSqlParserList(sqlParserList);
return paginationInterceptor;
}
}After this configuration, MyBatis‑Plus automatically appends the tenant_id condition to all CRUD operations. Example test code:
@Test
public void select() {
List<User> users = userMapper.selectList(Wrappers.<User>lambdaQuery().eq(User::getAge, 18));
users.forEach(System.out::println);
}
// Generated SQL:
// SELECT ... FROM sys_user WHERE sys_user.tenant_id = 'jiannan' AND is_delete = '0' AND age = ?3. Specific SQL Filtering
If certain SQL statements should not include the tenant_id, you can filter them in two ways.
Method 1: Add an ISqlParserFilter to the pagination interceptor (not recommended for many statements).
paginationInterceptor.setSqlParserFilter(new ISqlParserFilter() {
@Override
public boolean doFilter(MetaObject metaObject) {
MappedStatement ms = SqlParserHelper.getMappedStatement(metaObject);
if ("com.example.demo.mapper.UserMapper.selectList".equals(ms.getId())) {
return true; // skip tenant filter for this method
}
return false;
}
});Method 2: Use the @SqlParser annotation on mapper methods to control filtering.
/** User Mapper Interface */
public interface UserMapper extends BaseMapper<User> {
@SqlParser(filter = true)
int updateByMyWrapper(@Param(Constants.WRAPPER) Wrapper<User> userWrapper, @Param("user") User user);
}
# Enable SQL parser cache if using MyBatis‑Plus version >= 3.1.1
mybatis-plus:
global-config:
sql-parser-cache: trueUnderstanding multi‑tenant architecture and its implementation is valuable for developers building SaaS platforms, as it helps reduce costs while maintaining data isolation.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java High-Performance Architecture
Sharing Java development articles and resources, including SSM architecture and the Spring ecosystem (Spring Boot, Spring Cloud, MyBatis, Dubbo, Docker), Zookeeper, Redis, architecture design, microservices, message queues, Git, etc.
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.
