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")
}

注意事项

  1. 确保在创建租户特定数据时设置了正确的租户上下文
  2. 对于PostgreSQL,模式名称不能包含大写字母
  3. 对于MySQL,确保数据库用户有创建新数据库的权限

通过使用gorm-multitenancy,您可以轻松地为您的Golang应用程序添加多租户支持,同时保持代码的简洁和可维护性。


更多关于golang实现GORM多租户数据库管理的插件库gorm-multitenancy的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于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. 最佳实践

  1. 中间件集成:在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()
	}
}
  1. 租户识别:可以从JWT、子域名或请求头中获取租户ID

  2. 数据库索引:确保租户ID字段有索引以提高查询性能

7. 注意事项

  1. 插件会自动为所有实现了TenantModel接口的模型添加租户过滤条件
  2. 事务操作也会自动应用租户过滤
  3. 关联查询时,确保关联模型也实现了租户接口

通过gorm-multitenancy插件,你可以轻松实现多租户架构,保持代码简洁的同时确保数据隔离的安全性。

回到顶部