Enhance database configuration to support multiple data sources
- Updated .env.example to include optional configuration for additional database instances. - Refactored DatabaseConfig in config.go to accommodate a default database and additional instances. - Implemented loadAdditionalDBConfigs function to dynamically load configurations for extra databases. - Modified InitDB function in database.go to establish connections for both default and additional databases. - Updated README.md to document the new configuration options for connecting to multiple databases.
This commit is contained in:
@@ -8,6 +8,13 @@ DB_PORT=3306
|
|||||||
DB_USER=root
|
DB_USER=root
|
||||||
DB_PASSWORD=your_password
|
DB_PASSWORD=your_password
|
||||||
DB_NAME=wx_service
|
DB_NAME=wx_service
|
||||||
|
# 多数据源(可选)
|
||||||
|
# DB_INSTANCES=lawyer,reporting
|
||||||
|
# DB_LAWYER_HOST=127.0.0.1
|
||||||
|
# DB_LAWYER_PORT=3306
|
||||||
|
# DB_LAWYER_USER=another_user
|
||||||
|
# DB_LAWYER_PASSWORD=another_password
|
||||||
|
# DB_LAWYER_NAME=lawyer
|
||||||
|
|
||||||
# JWT配置
|
# JWT配置
|
||||||
JWT_SECRET=your-secret-key-change-in-production
|
JWT_SECRET=your-secret-key-change-in-production
|
||||||
|
|||||||
+40
-5
@@ -4,6 +4,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
@@ -27,6 +28,11 @@ type ServerConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DatabaseConfig struct {
|
type DatabaseConfig struct {
|
||||||
|
Default DatabaseInstanceConfig
|
||||||
|
Additional map[string]DatabaseInstanceConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
type DatabaseInstanceConfig struct {
|
||||||
Host string
|
Host string
|
||||||
Port string
|
Port string
|
||||||
User string
|
User string
|
||||||
@@ -94,17 +100,22 @@ func LoadConfig() {
|
|||||||
log.Println("未找到 .env 文件,使用环境变量")
|
log.Println("未找到 .env 文件,使用环境变量")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defaultDB := DatabaseInstanceConfig{
|
||||||
|
Host: getEnv("DB_HOST", "localhost"),
|
||||||
|
Port: getEnv("DB_PORT", "3306"),
|
||||||
|
User: getEnv("DB_USER", "root"),
|
||||||
|
Password: getEnv("DB_PASSWORD", ""),
|
||||||
|
DBName: getEnv("DB_NAME", "wx_service"),
|
||||||
|
}
|
||||||
|
|
||||||
AppConfig = &Config{
|
AppConfig = &Config{
|
||||||
Server: ServerConfig{
|
Server: ServerConfig{
|
||||||
Port: getEnv("SERVER_PORT", "8080"),
|
Port: getEnv("SERVER_PORT", "8080"),
|
||||||
Mode: getEnv("GIN_MODE", "debug"),
|
Mode: getEnv("GIN_MODE", "debug"),
|
||||||
},
|
},
|
||||||
Database: DatabaseConfig{
|
Database: DatabaseConfig{
|
||||||
Host: getEnv("DB_HOST", "localhost"),
|
Default: defaultDB,
|
||||||
Port: getEnv("DB_PORT", "3306"),
|
Additional: loadAdditionalDBConfigs(defaultDB),
|
||||||
User: getEnv("DB_USER", "root"),
|
|
||||||
Password: getEnv("DB_PASSWORD", ""),
|
|
||||||
DBName: getEnv("DB_NAME", "wx_service"),
|
|
||||||
},
|
},
|
||||||
JWT: JWTConfig{
|
JWT: JWTConfig{
|
||||||
Secret: getEnv("JWT_SECRET", "your-secret-key"),
|
Secret: getEnv("JWT_SECRET", "your-secret-key"),
|
||||||
@@ -148,6 +159,30 @@ func LoadConfig() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadAdditionalDBConfigs(defaultCfg DatabaseInstanceConfig) map[string]DatabaseInstanceConfig {
|
||||||
|
instances := strings.Split(getEnv("DB_INSTANCES", ""), ",")
|
||||||
|
result := make(map[string]DatabaseInstanceConfig)
|
||||||
|
for _, rawName := range instances {
|
||||||
|
name := strings.TrimSpace(rawName)
|
||||||
|
if name == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
upperName := strings.ToUpper(name)
|
||||||
|
prefix := "DB_" + upperName + "_"
|
||||||
|
result[strings.ToLower(name)] = DatabaseInstanceConfig{
|
||||||
|
Host: getEnv(prefix+"HOST", defaultCfg.Host),
|
||||||
|
Port: getEnv(prefix+"PORT", defaultCfg.Port),
|
||||||
|
User: getEnv(prefix+"USER", defaultCfg.User),
|
||||||
|
Password: getEnv(prefix+"PASSWORD", defaultCfg.Password),
|
||||||
|
DBName: getEnv(prefix+"NAME", defaultCfg.DBName),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(result) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func getEnv(key, defaultValue string) string {
|
func getEnv(key, defaultValue string) string {
|
||||||
if value := os.Getenv(key); value != "" {
|
if value := os.Getenv(key); value != "" {
|
||||||
return value
|
return value
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
2. 按实际环境填写以下变量:
|
2. 按实际环境填写以下变量:
|
||||||
- `SERVER_PORT`:HTTP 服务端口,例如 `8080`。
|
- `SERVER_PORT`:HTTP 服务端口,例如 `8080`。
|
||||||
- `DB_HOST/DB_PORT/DB_USER/DB_PASSWORD/DB_NAME`:MySQL 连接信息。
|
- `DB_HOST/DB_PORT/DB_USER/DB_PASSWORD/DB_NAME`:MySQL 连接信息。
|
||||||
|
- 若需连接额外数据库,可设置 `DB_INSTANCES=lawyer,reporting` 并依次提供 `DB_<NAME>_HOST/PORT/USER/PASSWORD/NAME`;未指定的字段会回落到默认数据库的同名配置。
|
||||||
3. 如果需要,替换 `GIN_MODE`、`JWT_SECRET` 等其他变量。
|
3. 如果需要,替换 `GIN_MODE`、`JWT_SECRET` 等其他变量。
|
||||||
4. 通过 `docs/sql/users.sql` 初始化 `mini_programs` 与 `users` 表,并插入每个小程序的 `name/app_id/app_secret`。
|
4. 通过 `docs/sql/users.sql` 初始化 `mini_programs` 与 `users` 表,并插入每个小程序的 `name/app_id/app_secret`。
|
||||||
|
|
||||||
|
|||||||
@@ -11,11 +11,38 @@ import (
|
|||||||
"gorm.io/gorm/logger"
|
"gorm.io/gorm/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
var DB *gorm.DB
|
var (
|
||||||
|
DB *gorm.DB
|
||||||
|
additionalDBs map[string]*gorm.DB
|
||||||
|
)
|
||||||
|
|
||||||
func InitDB() error {
|
func InitDB() error {
|
||||||
cfg := config.AppConfig.Database
|
cfg := config.AppConfig.Database
|
||||||
|
|
||||||
|
defaultDB, err := openConnection(cfg.Default)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("连接数据库失败: %v", err)
|
||||||
|
}
|
||||||
|
DB = defaultDB
|
||||||
|
log.Println("默认数据库连接成功")
|
||||||
|
|
||||||
|
if len(cfg.Additional) > 0 {
|
||||||
|
additionalDBs = make(map[string]*gorm.DB)
|
||||||
|
for name, instanceCfg := range cfg.Additional {
|
||||||
|
conn, err := openConnection(instanceCfg)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("连接数据库[%s]失败: %v", name, err)
|
||||||
|
}
|
||||||
|
additionalDBs[strings.ToLower(name)] = conn
|
||||||
|
log.Printf("数据库连接成功: %s\n", name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
additionalDBs = nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func openConnection(cfg config.DatabaseInstanceConfig) (*gorm.DB, error) {
|
||||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
|
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
|
||||||
cfg.User,
|
cfg.User,
|
||||||
cfg.Password,
|
cfg.Password,
|
||||||
@@ -24,17 +51,24 @@ func InitDB() error {
|
|||||||
cfg.DBName,
|
cfg.DBName,
|
||||||
)
|
)
|
||||||
|
|
||||||
var err error
|
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
|
||||||
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
|
|
||||||
Logger: logger.Default.LogMode(logger.Info),
|
Logger: logger.Default.LogMode(logger.Info),
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("连接数据库失败: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return db, nil
|
||||||
|
}
|
||||||
|
|
||||||
log.Println("数据库连接成功")
|
func GetAdditionalDB(name string) (*gorm.DB, bool) {
|
||||||
return nil
|
if name == "" || strings.EqualFold(name, "default") {
|
||||||
|
return DB, DB != nil
|
||||||
|
}
|
||||||
|
if additionalDBs == nil {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
db, ok := additionalDBs[strings.ToLower(name)]
|
||||||
|
return db, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func AutoMigrate(models ...interface{}) error {
|
func AutoMigrate(models ...interface{}) error {
|
||||||
|
|||||||
Reference in New Issue
Block a user