Skip to content

Conversation

@LanceAdd
Copy link
Contributor

gdb目前支持分库分表级别的多租户,补充一个行级多租户的实现

主要特性:

  1. 租户上下文管理

    • 提供WithTenantIdFieldWithTenantIdValue函数用于设置租户字段名和值到上下文中
    • 默认实现DefaultGetTenantIdFieldValue从上下文中获取租户信息
  2. 模型级租户支持

    • 在Model中添加Tenant()方法启用多租户功能
    • 支持通过UnTenant()方法禁用多租户功能
    • TenantOption可配置选项包括:
      • Enable: 控制是否启用租户功能
      • PropagateToJoins: 控制是否将租户条件应用于连接表
      • GetTenantIdFieldValueFunc: 自定义获取租户ID字段和值的函数
  3. 智能租户条件生成

    • 自动识别单表、JOIN表和逗号分隔的多表查询
    • 根据表结构检查租户字段是否存在
    • 支持多种租户值类型:
      • 基本类型(BaseType):使用等值匹配
      • 数组或切片类型(ArrayOrSliceType):使用IN条件
      • 空值类型(NullType):使用IS NULL条件
  4. 无缝集成

    • 租户条件会自动附加到所有查询语句中
    • 与现有的软删除、WHERE条件等功能协同工作
    • 不影响原有API使用方式
  5. 注意事项

    • WithTenantIdField设置的tenantIdField在构建过程中会检查对应的表字段中有没有这个字段,所以最好是多表的租户字段都相同,如果有需要我也可以加个配置让大家在不同表映射成不同的字段,看大家有没有需求

使用示例:

// 启用租户功能
ctx := WithTenantIdField(context.Background(), "tenant_id")
ctx = WithTenantIdValue(ctx, 1)

// 查询时自动添加租户条件
db.Model("user").Ctx(ctx).Tenant().All()

// 对于JOIN查询,可选择是否传播到连接表
db.Model("user u"). 
    LeftJoin("order o", "u.id=o.user_id").
    Ctx(ctx).
    Tenant(TenantOption{
        Enable: true,
        PropagateToJoins: true,
    }).
    All()

sql

SELECT * FROM user WHERE tenant_id = 1

SELECT * FROM user u LEFT JOIN order o ON u.id=o.user_id WHERE u.tenant_id = 1 AND o.tenant_id = 1

- 在 Model 结构体中新增 TenantOption 字段以支持租户配置
- 实现 Tenant 和 UnTenant 方法用于启用和禁用租户功能
- 新增 TenantMaintainer 结构体及配套方法处理租户条件注入
- 支持在查询中自动附加租户 ID 条件,包括对 JOIN 表的传播控制
- 提供上下文获取租户字段名和值的默认实现与自定义函数接口
- 根据不同数据类型(基础类型、数组/切片、空值)构建相应 SQL 条件
- 自动检测表结构中的租户字段是否存在以避免无效条件注入
- 新增 InsertNullValue 配置项以控制是否允许插入空租户ID
- 实现租户创建时自动填充租户字段逻辑
- 优化软删除与租户功能共存时的字段处理
- 统一条件生成函数命名并增强其健壮性
- 改进表名解析和缓存键生成方式以适配更多场景
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant