1 Star 0 Fork 0

yangtxiang/mg-fw

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
core.go 5.35 KB
一键复制 编辑 原始数据 按行查看 历史
yangtxiang 提交于 2024-04-08 17:48 +08:00 . fix bug
package db
import (
"database/sql"
"fmt"
"gitee.com/maglsoft/mg-fw/config"
"github.com/fsnotify/fsnotify"
"github.com/pkg/errors"
"github.com/spf13/viper"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"gorm.io/gorm/schema"
"log"
"net/url"
"sync"
)
type DatabaseInitor func(db *gorm.DB, dbName string)
var dbInitorList []DatabaseInitor
// RegisterDbInitor 注册数据初始化
func RegisterDbInitor(initor DatabaseInitor) {
if dbInitorList == nil {
dbInitorList = make([]DatabaseInitor, 0)
}
dbInitorList = append(dbInitorList, initor)
}
var _db *gorm.DB
// buildDbIfNotExists 数据库不存在时创建数据库
func buildDbIfNotExists(mysqlOptions *MySqlOptions) (isNew bool, err error) {
dns := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=true&loc=%s",
mysqlOptions.User,
mysqlOptions.Password,
mysqlOptions.Host,
mysqlOptions.Port,
"mysql",
mysqlOptions.Charset,
url.QueryEscape(mysqlOptions.Loc))
mDb, err := sql.Open("mysql", dns)
if err != nil {
return false, err
}
rs1, err := mDb.Query("SELECT * FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = ?", mysqlOptions.DbName)
if err != nil {
return false, err
}
defer rs1.Close()
if rs1.Next() {
return false, nil
}
sql := "CREATE DATABASE IF NOT EXISTS `" + mysqlOptions.DbName + "`" +
"CHARACTER SET utf8mb4 " +
"DEFAULT CHARACTER SET utf8mb4 " +
"COLLATE utf8mb4_general_ci " +
"DEFAULT COLLATE utf8mb4_general_ci;"
_, err = mDb.Exec(sql)
if err != nil {
return false, err
}
defer func() {
if mDb != nil {
if err := mDb.Close(); err != nil {
log.Printf("close mysql error:%v", err)
}
}
}()
return true, nil
}
// NewGormDB 新建数据库连接
func NewGormDB(options *MySqlOptions, isNew ...*bool) (*gorm.DB, error) {
isNewDb, err := buildDbIfNotExists(options)
if err != nil {
return nil, errors.Wrap(err, "初始化mysql数据库出错")
}
dns := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=true&loc=%s",
options.User,
options.Password,
options.Host,
options.Port,
options.DbName,
options.Charset,
url.QueryEscape(options.Loc))
gormOptions := &gorm.Config{
NamingStrategy: schema.NamingStrategy{
TablePrefix: "",
SingularTable: false, //true 使用单数表名,启用该选项后,`User`表将是 `user`
NameReplacer: nil,
NoLowerCase: false,
},
SkipDefaultTransaction: false,
}
if options.LogLevel == "" {
gormOptions.Logger = logger.Default.LogMode(logger.Info)
} else {
switch options.LogLevel {
case "all":
gormOptions.Logger = logger.Default.LogMode(logger.Silent)
break
case "error":
gormOptions.Logger = logger.Default.LogMode(logger.Error)
break
case "warn":
gormOptions.Logger = logger.Default.LogMode(logger.Warn)
break
case "info":
gormOptions.Logger = logger.Default.LogMode(logger.Info)
break
default:
gormOptions.Logger = logger.Default.LogMode(logger.Info)
}
}
db, err := gorm.Open(mysql.Open(dns), gormOptions)
if err != nil {
return nil, errors.Wrap(err, "连接mysql数据库出错")
}
sqlDB, _ := db.DB()
sqlDB.SetMaxOpenConns(options.Pool.MaxOpenConns)
sqlDB.SetMaxIdleConns(options.Pool.MaxIdleConns)
if len(isNew) > 0 {
*isNew[0] = isNewDb
}
return db, nil
}
func initDB(cfg *viper.Viper) *gorm.DB {
var err error
var db *gorm.DB
var sqlDB *sql.DB
mysqlOptions := NewMySqlOptions("mysql", cfg)
isNewDb, err := buildDbIfNotExists(mysqlOptions)
if err != nil {
panic(err)
}
dns := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=true&loc=%s",
mysqlOptions.User,
mysqlOptions.Password,
mysqlOptions.Host,
mysqlOptions.Port,
mysqlOptions.DbName,
mysqlOptions.Charset,
url.QueryEscape(mysqlOptions.Loc))
gormOptions := &gorm.Config{
NamingStrategy: schema.NamingStrategy{
TablePrefix: "",
SingularTable: false, //true 使用单数表名,启用该选项后,`User`表将是 `user`
NameReplacer: nil,
NoLowerCase: false,
},
Logger: logger.Default.LogMode(logger.Info),
SkipDefaultTransaction: false,
}
if _db != nil {
if sqlDB, err = _db.DB(); nil == err {
if err2 := sqlDB.Close(); err2 != nil {
log.Println(err2)
}
}
_db = nil
}
db, err = gorm.Open(mysql.Open(dns), gormOptions)
if err != nil {
panic("failed to connect database, err: " + err.Error())
}
sqlDB, _ = db.DB()
sqlDB.SetMaxOpenConns(mysqlOptions.Pool.MaxOpenConns)
sqlDB.SetMaxIdleConns(mysqlOptions.Pool.MaxIdleConns)
_db = db
if isNewDb {
for _, initor := range dbInitorList {
initor(_db, mysqlOptions.DbName)
}
}
return db
}
var once sync.Once
func GetDB(configFile ...string) *gorm.DB {
once.Do(func() {
cfg := config.GetConfig(configFile...)
cfg.OnConfigChange(func(in fsnotify.Event) {
initDB(cfg)
})
cfg.WatchConfig()
initDB(cfg)
})
return _db
}
// Transaction 使用事务调用
func Transaction(entry func(tx *gorm.DB) error) error {
tx := GetDB().Begin()
var err error
defer func() {
if r := recover(); r != nil {
if e, ok := r.(error); ok {
err = e
log.Printf("db.Transaction err:%v", e)
} else {
log.Printf("db.Transaction panic:%v", r)
}
}
if err != nil {
log.Printf("Transacation error:%v", err)
if e1 := tx.Rollback().Error; e1 != nil {
err = errors.Wrap(err, e1.Error())
}
} else {
if e1 := tx.Commit().Error; e1 != nil {
fmt.Printf("db commit error:%v", e1)
}
}
}()
err = entry(tx)
return err
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/maglsoft/mg-fw.git
git@gitee.com:maglsoft/mg-fw.git
maglsoft
mg-fw
mg-fw
v0.0.5

搜索帮助