在 Hibernate 中实现多租户(Multi-Tenancy)数据库架构主要有两种常见方式:
方式一:基于 Schema(每个租户一个独立的 schema)
实现思路:
每个租户的数据存放在不同的 schema 中(但结构一致),通过动态切换 schema 实现隔离。
实现步骤:
- 配置 Hibernate 多租户类型:
properties.put(Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
- 实现
MultiTenantConnectionProvider
接口:
这个类用于根据租户 ID 提供对应 schema 的连接。public class SchemaMultiTenantConnectionProvider implements MultiTenantConnectionProvider { @Override public Connection getConnection(String tenantIdentifier) { Connection connection = dataSource.getConnection(); connection.createStatement().execute("SET SCHEMA '" + tenantIdentifier + "'"); return connection; } }
- 实现
CurrentTenantIdentifierResolver
接口:
负责告诉 Hibernate 当前请求的租户 ID。public class CurrentTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver { @Override public String resolveCurrentTenantIdentifier() { return TenantContext.getCurrentTenant(); // 从上下文中获取租户信息 } @Override public boolean validateExistingCurrentSessions() { return true; } }
- 整合到 Hibernate
SessionFactory
:
配置MultiTenantConnectionProvider
和CurrentTenantIdentifierResolver
。
优点:
- 数据隔离彻底,安全性高。
- 易于数据迁移、备份。
缺点:
- 数据库管理复杂,schema 多时维护成本高。
- 连接池资源开销可能更大。
方式二:基于 Discriminator(共享 schema,通过字段区分租户)
实现思路:
所有租户的数据存在同一个 schema 的表中,通过额外字段(如 tenant_id
)标识租户。
实现步骤:
- 所有实体添加
tenant_id
字段:@Column(name = "tenant_id", updatable = false) private String tenantId;
- 使用 Hibernate 的
@Filter
实现租户隔离:@FilterDef(name = "tenantFilter", parameters = @ParamDef(name = "tenantId", type = "string")) @Filter(name = "tenantFilter", condition = "tenant_id = :tenantId") public class YourEntity { ... }
- 每次打开 Session 时设置过滤器参数:
session.enableFilter("tenantFilter").setParameter("tenantId", currentTenantId);
优点:
- 数据库管理简单,结构清晰。
- 更适用于租户数量庞大但数据量小的场景。
缺点:
- 安全性依赖应用层控制,容易因过滤器未开启而泄漏数据。
- 查询效率可能低于 schema 隔离(需频繁使用
tenant_id
作为条件)。
总结对比:
对比项 | 基于 Schema | 基于 Discriminator |
---|---|---|
数据隔离性 | 高(物理隔离) | 中(逻辑隔离) |
维护复杂度 | 高 | 低 |
查询性能 | 高(无额外条件) | 中(需过滤字段) |
多租户数量 | 中(受 schema 数限制) | 高(无限制) |
安全性 | 高 | 中,易出错 |
场景适用 | SaaS 企业客户、大客户 | 小型客户、大量长尾租户 |
如果你在开发一个面向企业级客户的 SaaS 系统,推荐 基于 schema;如果是面向中小客户的大量租户系统,基于 discriminator 更灵活、成本更低。