数据库应该可以支持多个库
看了下数据库配置这块,个人感觉是应该需要支持多个库的,目前我个人的改造方法如下,不知道合理不合理。
pkg/database/database.go
文件:
package database
import (
"database/sql"
"gorm.io/gorm"
)
type DBInfo struct {
DB *gorm.DB
SQLDB *sql.DB
}
var DBCollections map[string]*DBInfo
// GetDB 获取对应 database 的 连接
func DB(name ...string) *gorm.DB {
if len(name) > 0 {
if collect, ok := DBCollections[name[0]]; ok {
return collect.DB
}
return nil
}
return DBCollections["default"].DB
}
config/database.go
文件:
package config
import (
"gohub/passport/pkg/config"
)
func init() {
config.Add("database", func() map[string]interface{} {
return map[string]interface{}{
// 默认数据库
"connection": config.Env("DB_CONNECTION", "mysql"),
"mysql": map[string]interface{}{
// 默认数据库
"default": map[string]interface{}{
// 数据库连接
"host": config.Env("DB_HOST", "127.0.0.1"),
"port": config.Env("DB_PORT", "3306"),
"database": config.Env("DB_DATABASE", ""),
"username": config.Env("DB_USERNAME", ""),
"password": config.Env("DB_PASSWORD", ""),
"charset": "utf8mb4",
// 日志级别 1 Silent 2 Error 3 Warn 4 Info
"log_level": config.GetInt("DB_LOGGER_LEVEL", 4),
// 连接池配置
"max_idle_connections": config.Env("DB_MAX_IDLE_CONNECTIONS", 100),
"max_open_connections": config.Env("DB_MAX_OPEN_CONNECTIONS", 25),
"max_life_seconds": config.Env("DB_MAX_LIFE_SECONDS", 5*60),
},
},
"sqlite": map[string]interface{}{
"default": map[string]interface{}{
"database": config.Env("DB_SQL_FILE", "database/database.db"),
},
},
}
})
}
bootstrap/database.go
文件
package bootstrap
import (
"database/sql"
"errors"
"fmt"
"time"
"gorm.io/driver/mysql"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"gohub/passport/pkg/config"
"gohub/passport/pkg/database"
)
// SetupDB 初始化数据库和orm
func SetupDB() {
var dbConfigs map[string]gorm.Dialector
switch config.Get("database.connection") {
case "mysql":
connectInfo := config.GetStringMapString("database.mysql")
for name := range connectInfo {
dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=%v&parseTime=True&multiStatements=true&loc=Local",
config.Get("database.mysql."+name+".username"),
config.Get("database.mysql."+name+".password"),
config.Get("database.mysql."+name+".host"),
config.Get("database.mysql."+name+".port"),
config.Get("database.mysql."+name+".database"),
config.Get("database.mysql."+name+".charset"),
)
if dbConfigs == nil {
dbConfigs = make(map[string]gorm.Dialector, len(connectInfo))
}
dbConfigs[name] = mysql.New(mysql.Config{
DSN: dsn,
})
}
case "sqlite":
connectInfo := config.GetStringMapString("database.sqlite")
for name := range connectInfo {
database := config.Get("database.sqlite." + name + ".database")
if dbConfigs == nil {
dbConfigs = make(map[string]gorm.Dialector, len(connectInfo))
}
dbConfigs[name] = sqlite.Open(database)
}
default:
panic(errors.New("database connection not supported"))
}
for k, v := range dbConfigs {
if database.DBCollections == nil {
database.DBCollections = make(map[string]*database.DBInfo, len(dbConfigs))
}
db, sqlDb, err := connect(v, logger.Default.LogMode(logger.LogLevel(config.GetInt("database.mysql."+k+".log_level"))))
if err != nil {
panic(err)
}
dbStruct := &database.DBInfo{
DB: db,
SQLDB: sqlDb,
}
database.DBCollections[k] = dbStruct
database.DBCollections[k].SQLDB.SetMaxIdleConns(config.GetInt("database.mysql." + k + ".max_idle_connections"))
database.DBCollections[k].SQLDB.SetMaxOpenConns(config.GetInt("database.mysql." + k + ".max_open_connections"))
database.DBCollections[k].SQLDB.SetConnMaxLifetime(time.Duration(config.GetInt("database.mysql."+k+".max_life_seconds")) * time.Second)
}
}
// connect 连接数据库
func connect(dbConfig gorm.Dialector, _logger logger.Interface) (*gorm.DB, *sql.DB, error) {
db, err := gorm.Open(
dbConfig,
&gorm.Config{
Logger: _logger,
},
)
if err != nil {
return nil, nil, err
}
sqlDb, err := db.DB()
if err != nil {
return nil, nil, err
}
return db, sqlDb, nil
}
这边改造是基于项目有可能不单纯使用一个库的原则考虑的,因为我司目前项目就是差不多有三十多个库,可能会使用到其他库。
本帖已被设为精华帖!
本帖由系统于 2个月前 自动加精
这种多数据库的连接,关于数据库的选择是如何优雅的处理呢?比如在 app/models/user.go 里面,有一个
func(userModel *User) Create()
方法。我目前想到的方法是,调用user.Create()
方法的时候,传入driver
参数。app/models/user.go 中,修改 Create() 方法为:
但是如果这么做的话,是不是意味着在 models 中所有操作 db 的方法,都需要传入
driver
参数呢?是否有优雅的方式来实现在 modes/xxx.go 中关于数据库句柄的选择呢?