Skip to content

租户隔离边界

Forge 通过 TenantLineInnerInterceptor 实现多租户数据隔离。你在开发时需要了解哪些表需要 tenant_id,以及跨租户查询的注意事项。

工作原理

TenantLineInnerInterceptor 是 MyBatis-Plus 提供的租户拦截器,它在 SQL 执行前自动追加租户条件:

sql
-- 你写的 SQL
SELECT * FROM sys_user WHERE status = '0'

-- 拦截器自动改写为
SELECT * FROM sys_user WHERE status = '0' AND tenant_id = 1

拦截器对 SELECTUPDATEDELETE 都会自动追加 WHERE tenant_id = ?

租户 ID 规则

规则说明
业务数据 tenant_id必须设为 1(默认租户)
禁止设为 00 的数据对所有租户不可见
sys_resource(菜单/权限)不受租户拦截,tenant_id 设为 1
sql
-- 正确:内置数据 tenant_id = 1
INSERT INTO sys_dict_type (dict_name, dict_type, tenant_id)
VALUES ('性别', 'sys_user_sex', 1);

-- 禁止:tenant_id = 0,数据不可见
INSERT INTO sys_dict_type (dict_name, dict_type, tenant_id)
VALUES ('性别', 'sys_user_sex', 0);

需要 tenant_id 的表

表类型需要 tenant_id说明
业务数据表用户、订单、配置等
系统管理表sys_usersys_role
字典表sys_dict_typesys_dict_data
菜单/权限表sys_resource(不拦截,但字段必须有)
Flowable 引擎表框架管理,不纳入
框架运行表forge_schema_history

跨租户查询

如果业务需要跨租户查询(如平台管理员查看所有租户数据),需要忽略租户拦截:

java
// 方式一:指定方法忽略租户
@InterceptorIgnore(tenantLine = "true")
List<SysUserEntity> selectAllTenantUsers();
xml
<!-- Mapper XML 中不需要手动写 tenant_id,拦截器会自动处理 -->
<select id="selectUserPage" resultType="SysUserVO">
    SELECT u.id, u.username, u.nickname
    FROM sys_user u
    WHERE u.del_flag = 0
</select>

注意事项

  • 不要在 XML 中手动写 AND tenant_id = #{tenantId},拦截器会自动追加,否则会重复条件
  • 新建表时必须包含 tenant_id 字段,否则拦截器追加条件时 SQL 报错
  • 如果表不需要租户隔离,在 TenantLineInnerInterceptor 配置中排除该表
  • 前端不需要传 tenantId,后端从上下文自动获取

Forge Admin — 基于 Vue3 + Spring Boot 的企业级后台管理框架