mybatis-plus通过tenantlineinnerinterceptor实现多租户数据隔离,自动在select/update/delete的where后追加tenant_id=?过滤;需手动管理threadlocal租户上下文,并配置忽略表或注解跳过隔离。

MyBatis-Plus 通过 多租户插件(TenantLineInnerInterceptor) 实现数据隔离,核心是在 SQL 的 WHERE 条件中自动追加租户 ID 过滤,无需手动修改每个查询逻辑。
启用多租户插件
在 MyBatis-Plus 配置类中注册 TenantLineInnerInterceptor,并指定租户字段名(如 tenant_id):
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
TenantLineInnerInterceptor tenantInterceptor = new TenantLineInnerInterceptor();
tenantInterceptor.setTenantIdColumn("tenant_id"); // 租户字段名
interceptor.addInnerInterceptor(tenantInterceptor);
return interceptor;
}
该插件会拦截所有 SELECT、UPDATE、DELETE 语句,在 WHERE 后自动添加 AND tenant_id = ?。
设置当前租户 ID
MyBatis-Plus 不负责租户上下文管理,需自行在线程级存储当前租户 ID。推荐使用 ThreadLocal + 拦截器/过滤器提取:
- 在请求入口(如 Spring MVC 拦截器或 Filter)中解析租户标识(如 header、token、子域名)
- 调用
TenantHandler.setTenantId("t123")或自定义TenantLineInnerInterceptor子类重写getTenantId()方法 - 务必在请求结束时清理 ThreadLocal,避免线程复用导致脏数据
跳过多租户过滤的场景
某些表(如系统字典、租户元信息表)不应被租户隔离,可通过以下方式排除:
- 配置插件忽略表:调用
tenantInterceptor.setIgnoreTables("sys_tenant", "sys_dict") - SQL 中显式使用
@SqlParser(filter = true)注解(仅适用于 Mapper 方法) - 动态切换:通过
TenantLineInnerInterceptor.ignoreTable(String tableName)临时忽略(需注意线程安全)
注意事项与常见问题
多租户是逻辑隔离,不是物理隔离。生产环境若租户数据量极大或安全要求极高,应结合数据库分库分表或行级权限控制:
- INSERT 语句也会自动填充租户字段,前提是实体类中对应字段加了
@TableField(fill = FieldFill.INSERT)并配置自动填充处理器 - 联表查询(JOIN)不会自动为被关联表添加租户条件,需手动确保关联表也受租户约束或同样配置 ignore
- 全局唯一索引(如手机号、用户名)需加上租户 ID 组合,否则跨租户可能冲突
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











