Mastering Multi‑Tenant Architecture with MyBatis‑Plus: A Complete Guide
This article explains multi‑tenant concepts, compares three data isolation strategies, and provides a step‑by‑step MyBatis‑Plus implementation—including pagination interceptor configuration, code examples, testing, and ways to exclude specific SQL from tenant filtering—helping developers build scalable SaaS back‑ends.
1. Introduction
Multi‑tenant is a software architecture technique where multiple users share the same system while keeping their data isolated. A typical scenario is an H5 application deployed in different hospital apps; each hospital (tenant) sends its data with a tenant ID so the backend can separate the data.
2. Data Isolation Schemes
Independent Database: One database per tenant, offering the highest isolation and security but increasing cost.
Shared Database – Separate Schema: Tenants share a single database but each has its own schema (database user).
Shared Database – Shared Schema: Tenants share the same database and schema, with a tenant_id column added to tables; this provides the lowest isolation but the lowest cost.
3. Implementation with MyBatis‑Plus
The article chooses scheme three (shared database, shared schema) for minimal server cost. MyBatis‑Plus offers a multi‑tenant solution based on the pagination interceptor.
@Configuration
public class MyBatisPlusConfig {
/**
* Pagination interceptor
* @return
*/
@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() {
// Return current tenant ID, e.g., from cookie or cache
return new StringValue("jiannan");
}
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
@Override
public boolean doTableFilter(String tableName) {
// Return true to filter a specific table, false otherwise
return false;
}
});
sqlParserList.add(tenantSqlParser);
paginationInterceptor.setSqlParserList(sqlParserList);
return paginationInterceptor;
}
}After configuration, all CRUD operations automatically add the tenant_id condition. Example test:
@Test
public void select() {
List<User> users = userMapper.selectList(Wrappers.<User>lambdaQuery().eq(User::getAge, 18));
users.forEach(System.out::println);
}
DEBUG==> Preparing: SELECT id, login_name, name, password, email, salt, sex, age, phone, user_type, status, organization_id, create_time, update_time, version, tenant_id FROM sys_user WHERE sys_user.tenant_id = 'jiannan' AND is_delete = '0' AND age = ?
DEBUG==> Parameters: 18(Integer)
DEBUG<== Total: 04. Specific SQL Filtering
If certain SQL statements should not carry the tenant filter, two approaches are provided:
Configure an ISqlParserFilter in the pagination interceptor to exclude specific mapper methods.
Use the @SqlParser(filter = true) annotation on mapper methods (available only on mapper interfaces).
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;
}
return false;
}
}); 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 in MyBatis‑Plus configuration (for versions ≥3.1.1):
mybatis-plus:
global-config:
sql-parser-cache: trueMulti‑tenant SaaS systems are increasingly important for B‑to‑B services, and mastering these techniques can benefit career development.
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.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
