1

我有一个要求,我的应用程序与不同的数据库通信。我如何管理 gorm 中的连接。gorm 有什么方法支持多个数据库的连接管理。或者我需要创建包含所有数据库连接的地图。

if val, ok := selector.issure_db[issuer]; ok {
    return val , nil;

} else {

    var dbo  *db.DB;

    selector.mu.Lock()

    dbo, err := db.NewDb(Config)

    if err != nil {
        boot.Logger(ctx).Fatal(err.Error())
    }

    selector.issure_db[issuer] = dbo;

    selector.mu.Unlock()

    return repo ,nil;
}

有没有更好的方法来做到这一点?

4

2 回答 2

1

您可以为 GORM 使用dbresolver插件。它管理多个源和副本,并为组维护一个底层连接池。您甚至可以使用配置将应用程序中的模型映射到正确的数据库。

文档中的示例:

import (
  "gorm.io/gorm"
  "gorm.io/plugin/dbresolver"
  "gorm.io/driver/mysql"
)

db, err := gorm.Open(mysql.Open("db1_dsn"), &gorm.Config{})

db.Use(dbresolver.Register(dbresolver.Config{
  // use `db2` as sources, `db3`, `db4` as replicas
  Sources:  []gorm.Dialector{mysql.Open("db2_dsn")},
  Replicas: []gorm.Dialector{mysql.Open("db3_dsn"), mysql.Open("db4_dsn")},
  // sources/replicas load balancing policy
  Policy: dbresolver.RandomPolicy{},
}).Register(dbresolver.Config{
  // use `db1` as sources (DB's default connection), `db5` as replicas for `User`, `Address`
  Replicas: []gorm.Dialector{mysql.Open("db5_dsn")},
}, &User{}, &Address{}).Register(dbresolver.Config{
  // use `db6`, `db7` as sources, `db8` as replicas for `orders`, `Product`
  Sources:  []gorm.Dialector{mysql.Open("db6_dsn"), mysql.Open("db7_dsn")},
  Replicas: []gorm.Dialector{mysql.Open("db8_dsn")},
}, "orders", &Product{}, "secondary"))
于 2021-09-10T16:57:40.753 回答
1

您可以创建一个名为 database 的包并在 init.go 文件中编写一个 init 函数,该函数可以为您拥有的每个数据库创建一个 DB 对象来连接数据库。您可以在应用程序中的任何地方使用此 db 对象,这也将启用连接池。

初始化.go

var db *gorm.DB

func init() {
    var err error
    dataSourceName := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", dbUser, dbPassword, dbHost, dbPort, dbName)
    db, err = gorm.Open("mysql", dataSourceName)
    db.DB().SetConnMaxLifetime(10 * time.Second)
    db.DB().SetMaxIdleConns(10)

    //initialise other db objects here
}

用户.go

func getFirstUser() (user User) {
    db.First(&user)
    return
}

PS> 如果您必须连接到 1 或 2 个数据库,此解决方案会很有效。如果您需要同时连接到多个数据库,您应该使用 dbresolver 插件。

旧答案

您可以编写一个单独的函数,每次调用该函数时返回当前数据库连接对象。

func getDBConnection(dbUser, dbPassword, dbHost, dbName string) (db *gorm.DB, err error) {
    dataSourceName := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", dbUser, dbPassword, dbHost, dbPort, dbName)
    db, err = gorm.Open("mysql", dataSourceName)
    db.DB().SetConnMaxLifetime(10 * time.Second)
    return
}

并且每次调用 getDBConnection 函数后调用 defer db.Close() 。

func getFirstUser() (user User) {
    db, _ := getDBConnection()
    defer db.Close()
    db.First(&user)
    return
}

这样,每次执行查询后,您的连接都会关闭。

于 2020-11-05T19:15:11.747 回答