gpt4 book ai didi

sql - 模式交换支持 Go GORM

转载 作者:数据小太阳 更新时间:2023-10-29 03:26:02 27 4
gpt4 key购买 nike

我正在编写一个 REST API,我需要在其中动态部署到多个模式的连接。

示例:我有两个模式,我需要根据哪个用户尝试使用数据来更改它们。

想法是有许多其他方案,每个用户一个。

我看到了这个问题,但使用的示例是 static需要找到一种动态变化的方法。我会将用户模式放入 JWT token 中。

我的项目:Panda-API

有什么建议吗?

最佳答案

选项 1

您可以更改 database.GetConnection() 方法以接收用户名并直接连接到数据库,而无需更改所有服务和模型。您将用户存储在 security_middleware.go 上的 gin.Context 对象中,因此您可以从 Controller 上获取它并将其传递给服务,以便它们获得相应的数据库连接。

但是为此,您必须删除必须存储 DB 对象的 Singleton 模式并创建一个 DB 对象池,也许在 map[string]*DB 中而不是缓存服务包中的 DB 对象,您缓存数据库包中的所有用户 DB 对象。

你的 database/database.go 文件看起来像这样:

// Add sync import to handle concurrent access to the cache
import "sync"

// ... existent code

// DB objects cache
type DBs struct {
Cache map[string]*gorm.DB
sync.RWMutex
}

var dbs *DBs

// Init cache
func init() {
dbs = DBs{
Cache: make(map[string]*gorm.DB)
}
}

func GetConnection(username string) *gorm.DB {
// Try to get connection from the cache
dbs.RLock()
if db, ok := dbs.Cache[username]; ok {
dbs.RUnlock()
return db
}

// Figure out DB_NAME dynamically here, based on username...
//...
dbName := figuredOutDB_NAME

db, err := gorm.Open(DB_DATABASE, "host=" + DB_HOST + " user=" + DB_USER + " dbname=" + dbName + " sslmode=" + DB_SSL_MODE + " password=" + DB_PASSWORD)

if err != nil {
panic(err)
}

//Ativa log de todas as saidas da conexão (SQL)
db.LogMode(GetENVLogMode())
//Seta o maximo de conexões
db.DB().SetMaxIdleConns(DB_MAX_CONNECTION)
db.DB().SetMaxOpenConns(DB_MAX_CONNECTION)

DropTablesIfExists(db)
AutoMigrate(db)
AutoPopulate(db)
AddForeignKeys(db)

// Save connection to cache
dbs.Lock()
dbs.Cache[username] = db
dbs.Unlock()

return db
}

// ... and so on

然后删除 services/services.go 文件,因为它没有用。并更改您的服务方法以接收用户名作为参数,而不是使用 Con 变量,每次调用 Con := database.GetConnection(username)

我希望这能让您了解一个可能的解决方案。当然可能还有其他选择,但这就是我现在能想到的。

我看到这个方法的问题是你会为系统中的每个用户打开一个连接(和一个 gorm.DB 对象),不确定你期望有多少用户,但这可能是一个问题.

选项 2

另一种解决方案是在服务上进行相同的更改,以便它们在所有方法上都将用户作为参数接收,但不是获取新连接,而是将用户名/数据库名称设置为自定义模型属性,您可以使用它来实现您自己的 Model.TableName() 方法,该方法使用该属性返回 schema.table 格式。

因此,您将模型更改为拥有一个带有 setter 的私有(private)属性,例如:

type Person struct {
schemaName string

// ... existent properties.
}

func (p *Person) SetUser(u string) string {
// Figure out the schema name from the username
//...

p.schemaName = schema
}

func (p *Person) TableName() string {
return p.schemaName + ".persons"
}

然后,在您的服务上,您每次创建新模型实例时都会设置用户:

func GetPeople(pag helpers.Pagination, q url.Values, username string) models.People {

var people models.People
(&people).SetUser(username)

db := Con

// ... and so on

这是我现在可以考虑的 2 种可能的解决方案。可能会有更多更好的,但希望能有所帮助。

关于sql - 模式交换支持 Go GORM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41618602/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com