golang实现GORM多租户数据库管理的插件库gorm-multitenancy的使用
GORM多租户数据库管理的插件库gorm-multitenancy使用指南
概述
gorm-multitenancy提供了一个Go框架,用于构建多租户应用程序,简化租户管理和模型迁移。它通过一个与GORM兼容的统一、数据库无关的API抽象了多租户的复杂性。
多租户实现方法
数据库多租户有三种常见方法:
- 共享数据库,共享模式
- 共享数据库,独立模式
- 独立数据库
根据使用的数据库,该包使用"共享数据库,独立模式"或"独立数据库"策略,通过提供定制的驱动程序确保与现有数据库配置的平滑集成。
特性
- GORM集成:简化GORM在多租户环境中的使用
- 自定义数据库驱动程序:增强现有驱动程序以便轻松设置多租户
- HTTP中间件:为Web应用程序提供简单的租户上下文管理中间件
支持的数据库
数据库 | 实现方法 |
---|---|
PostgreSQL | 共享数据库,独立模式 |
MySQL | 独立数据库 |
安装
安装核心包:
go get -u github.com/bartventer/gorm-multitenancy/v8
安装数据库特定驱动:
# PostgreSQL
go get -u github.com/bartventer/gorm-multitenancy/postgres/v8
# MySQL
go get -u github.com/bartventer/gorm-multitenancy/mysql/v8
可选安装路由特定中间件:
# Echo
go get -u github.com/bartventer/gorm-multitenancy/middleware/echo/v8
# Gin
go get -u github.com/bartventer/gorm-multitenancy/middleware/gin/v8
# Iris
go get -u github.com/bartventer/gorm-multitenancy/middleware/iris/v8
# Net/HTTP
go get -u github.com/bartventer/gorm-multitenancy/middleware/nethttp/v8
使用示例
PostgreSQL示例
package main
import (
"fmt"
"log"
"github.com/bartventer/gorm-multitenancy/datastore"
"github.com/bartventer/gorm-multitenancy/postgres/v8"
"gorm.io/gorm"
)
// Tenant模型
type Tenant struct {
gorm.Model
Name string `gorm:"unique;not null"`
}
// User模型
type User struct {
gorm.Model
Name string
TenantID uint // 租户ID字段
}
func main() {
// 初始化主数据库连接
mainDB, err := postgres.Open("host=localhost user=postgres password=postgres dbname=main_db port=5432 sslmode=disable")
if err != nil {
log.Fatal(err)
}
// 创建多租户配置
config := &datastore.Config{
TenantModel: Tenant{}, // 租户模型
TenantIDField: "TenantID", // 租户ID字段名
PublicSchemaName: "public", // 公共模式名
}
// 初始化多租户DB
multiTenantDB, err := postgres.New(mainDB, config)
if err != nil {
log.Fatal(err)
}
// 自动迁移模型
err = multiTenantDB.AutoMigrate(&Tenant{}, &User{})
if err != nil {
log.Fatal(err)
}
// 创建租户
tenant := Tenant{Name: "tenant1"}
if err := multiTenantDB.Create(&tenant).Error; err != nil {
log.Fatal(err)
}
// 设置当前租户上下文
multiTenantDB = multiTenantDB.WithContext(datastore.NewTenantContext(tenant.ID))
// 为当前租户创建用户
user := User{Name: "John Doe", TenantID: tenant.ID}
if err := multiTenantDB.Create(&user).Error; err != nil {
log.Fatal(err)
}
fmt.Println("User created successfully for tenant:", tenant.Name)
}
Gin中间件示例
package main
import (
"github.com/bartventer/gorm-multitenancy/datastore"
"github.com/bartventer/gorm-multitenancy/middleware/gin/v8"
"github.com/bartventer/gorm-multitenancy/postgres/v8"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
var multiTenantDB *datastore.MultiTenantDB
func main() {
// 初始化数据库连接和多租户配置(同上)
r := gin.Default()
// 使用多租户中间件
r.Use(ginmulti.TenantMiddleware(multiTenantDB, func(c *gin.Context) (string, error) {
// 从请求中获取租户ID,例如从header、query参数或JWT token中
tenantID := c.GetHeader("X-Tenant-ID")
return tenantID, nil
}))
r.GET("/users", func(c *gin.Context) {
// 从上下文中获取DB实例
db := ginmulti.TenantDBFromContext(c)
var users []User
if err := db.Find(&users).Error; err != nil {
c.JSON(500, gin.H{"error": err.Error()})
return
}
c.JSON(200, users)
})
r.Run(":8080")
}
注意事项
- 确保在创建租户特定数据时设置了正确的租户上下文
- 对于PostgreSQL,模式名称不能包含大写字母
- 对于MySQL,确保数据库用户有创建新数据库的权限
通过使用gorm-multitenancy,您可以轻松地为您的Golang应用程序添加多租户支持,同时保持代码的简洁和可维护性。
更多关于golang实现GORM多租户数据库管理的插件库gorm-multitenancy的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang实现GORM多租户数据库管理的插件库gorm-multitenancy的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
GORM多租户数据库管理插件gorm-multitenancy使用指南
gorm-multitenancy是一个为GORM设计的轻量级多租户插件,它可以帮助开发者轻松实现多租户数据隔离。下面我将详细介绍如何使用这个插件。
1. 安装插件
首先需要安装gorm-multitenancy插件:
go get github.com/linclin/gorm-multitenancy
2. 基本使用
2.1 初始化插件
package main
import (
"gorm.io/gorm"
"gorm.io/driver/mysql"
"github.com/linclin/gorm-multitenancy"
)
func main() {
dsn := "user:password@tcp(127.0.0.1:3306)/database?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// 初始化多租户插件
plugin := multitenancy.New()
db.Use(plugin)
}
2.2 设置租户上下文
// 设置当前租户ID
func setTenant(db *gorm.DB, tenantID string) *gorm.DB {
return db.Set(multitenancy.TenantIDKey, tenantID)
}
// 使用示例
func main() {
// ...初始化代码...
// 为租户A操作
tenantADB := setTenant(db, "tenant_a")
// 为租户B操作
tenantBDB := setTenant(db, "tenant_b")
}
3. 模型定义
在模型中加入租户ID字段:
type User struct {
gorm.Model
Name string `gorm:"size:255"`
Email string `gorm:"size:255;uniqueIndex"`
TenantID string `gorm:"size:36;index"` // 租户ID字段
}
// 实现TenantModel接口
func (u *User) GetTenantID() string {
return u.TenantID
}
func (u *User) SetTenantID(tenantID string) {
u.TenantID = tenantID
}
4. CRUD操作
4.1 创建记录
func createUser(db *gorm.DB, name, email string) error {
user := &User{
Name: name,
Email: email,
}
return db.Create(user).Error
}
// 使用
tenantADB := setTenant(db, "tenant_a")
createUser(tenantADB, "Alice", "alice@example.com")
4.2 查询记录
func getUserByEmail(db *gorm.DB, email string) (*User, error) {
var user User
err := db.Where("email = ?", email).First(&user).Error
return &user, err
}
// 使用 - 只会查询当前租户下的用户
user, err := getUserByEmail(tenantADB, "alice@example.com")
4.3 更新和删除
// 更新
db.Model(&User{}).Where("id = ?", 1).Update("name", "Alice Updated")
// 删除
db.Delete(&User{}, 1)
5. 高级功能
5.1 跨租户查询
如果需要跨租户查询,可以临时禁用租户过滤:
// 获取所有租户的用户(管理员权限)
var allUsers []User
db.Scopes(multitenancy.IgnoreTenantFilter()).Find(&allUsers)
5.2 自定义租户字段名
默认使用"tenant_id"作为租户字段,可以自定义:
plugin := multitenancy.New(
multitenancy.WithTenantColumn("custom_tenant_id"),
)
5.3 租户表过滤
可以配置某些表不进行租户过滤:
plugin := multitenancy.New(
multitenancy.WithSkipTables([]string{"system_settings", "global_configs"}),
)
6. 最佳实践
- 中间件集成:在Web框架(如Gin)的中间件中设置租户ID
func TenantMiddleware(db *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {
tenantID := c.GetHeader("X-Tenant-ID")
if tenantID == "" {
c.AbortWithStatusJSON(400, gin.H{"error": "tenant id required"})
return
}
c.Set("db", db.Set(multitenancy.TenantIDKey, tenantID))
c.Next()
}
}
-
租户识别:可以从JWT、子域名或请求头中获取租户ID
-
数据库索引:确保租户ID字段有索引以提高查询性能
7. 注意事项
- 插件会自动为所有实现了TenantModel接口的模型添加租户过滤条件
- 事务操作也会自动应用租户过滤
- 关联查询时,确保关联模型也实现了租户接口
通过gorm-multitenancy插件,你可以轻松实现多租户架构,保持代码简洁的同时确保数据隔离的安全性。