diff --git a/gorm/gorm.go b/gorm/gorm.go index fbb0086..b1928ab 100644 --- a/gorm/gorm.go +++ b/gorm/gorm.go @@ -12,16 +12,23 @@ import ( "github.com/sunmi-OS/gocore/xlog" ) -type Client struct { - maps sync.Map - defaultDbName string -} - -var _Gorm *Client +var ( + Gorm sync.Map + defaultName = "dbDefault" +) -func Gorm() *Client { - return _Gorm -} +var ( + // ErrRecordNotFound record not found error, happens when haven't find any matched data when looking up with a struct + ErrRecordNotFound = gorm.ErrRecordNotFound + // ErrInvalidSQL invalid SQL error, happens when you passed invalid SQL + ErrInvalidSQL = gorm.ErrInvalidSQL + // ErrInvalidTransaction invalid transaction when you are trying to `Commit` or `Rollback` + ErrInvalidTransaction = gorm.ErrInvalidTransaction + // ErrCantStartTransaction can't start transaction when you are trying to start one with `Begin` + ErrCantStartTransaction = gorm.ErrCantStartTransaction + // ErrUnaddressable unaddressable value + ErrUnaddressable = gorm.ErrUnaddressable +) // 初始化Gorm func NewDB(dbname string) { @@ -29,11 +36,7 @@ func NewDB(dbname string) { orm *gorm.DB err error ) - if _Gorm == nil { - _Gorm = &Client{defaultDbName: defaultName} - } - // openORM err = retry.Retry(func() error { orm, err = openORM(dbname) if err != nil { @@ -46,17 +49,16 @@ func NewDB(dbname string) { panic(err) } - // store db client - _Gorm.maps.Store(dbname, orm) + Gorm.Store(dbname, orm) } -// SetDefaultName 设置默认DB Name -func (c *Client) SetDefaultName(dbName string) { - c.defaultDbName = dbName +// 设置获取db的默认值 +func SetDefaultName(dbname string) { + defaultName = dbname } -// NewOrUpdateDB 初始化或更新Gorm -func (c *Client) NewOrUpdateDB(dbname string) error { +// 初始化Gorm +func UpdateDB(dbname string) error { var ( orm *gorm.DB err error @@ -76,11 +78,11 @@ func (c *Client) NewOrUpdateDB(dbname string) error { } // second: load gorm client - v, _ := c.maps.Load(dbname) + v, _ := Gorm.Load(dbname) // third: delete old gorm client and store the new gorm client - c.maps.Delete(dbname) - c.maps.Store(dbname, orm) + Gorm.Delete(dbname) + Gorm.Store(dbname, orm) // fourth: if old client is not nil, delete and close connection if v != nil { @@ -89,30 +91,30 @@ func (c *Client) NewOrUpdateDB(dbname string) error { return nil } +// Deprecated +// 通过名称获取Gorm实例 +func GetORMByName(dbname string) *gorm.DB { + v, ok := Gorm.Load(dbname) + if ok { + return v.(*gorm.DB) + } + return nil +} + // GetORM 获取默认的Gorm实例 // 目前仅支持 不传 或者仅传一个 dbname -func (c *Client) GetORM(dbname ...string) *gorm.DB { - name := c.defaultDbName +func GetORM(dbname ...string) *gorm.DB { + name := defaultName if len(dbname) == 1 { name = dbname[0] } - - v, ok := c.maps.Load(name) + v, ok := Gorm.Load(name) if ok { return v.(*gorm.DB) } return nil } -func (c *Client) Close() { - c.maps.Range(func(dbName, orm interface{}) bool { - xlog.Warnf("close db %s", dbName) - c.maps.Delete(dbName) - orm.(*gorm.DB).Close() - return true - }) -} - func openORM(dbname string) (*gorm.DB, error) { //默认配置 viper.C.SetDefault(dbname, map[string]interface{}{ diff --git a/orm/gorm.go b/orm/gorm.go new file mode 100644 index 0000000..72b69db --- /dev/null +++ b/orm/gorm.go @@ -0,0 +1,152 @@ +package orm + +import ( + "sync" + "time" + + "github.com/jinzhu/gorm" + _ "github.com/jinzhu/gorm/dialects/mysql" + "github.com/sunmi-OS/gocore/retry" + "github.com/sunmi-OS/gocore/viper" + "github.com/sunmi-OS/gocore/xlog" +) + +type Client struct { + maps sync.Map + defaultDbName string +} + +var _Gorm *Client + +func Gorm() *Client { + return _Gorm +} + +// 初始化Gorm +func NewDB(dbname string) { + var ( + orm *gorm.DB + err error + ) + if _Gorm == nil { + _Gorm = &Client{defaultDbName: defaultName} + } + + // openORM + err = retry.Retry(func() error { + orm, err = openORM(dbname) + if err != nil { + xlog.Errorf("NewDB(%s) error:%+v", dbname, err) + return err + } + return nil + }, 5, 3*time.Second) + if err != nil || orm == nil { + panic(err) + } + + // store db client + _Gorm.maps.Store(dbname, orm) +} + +// SetDefaultName 设置默认DB Name +func (c *Client) SetDefaultName(dbName string) { + c.defaultDbName = dbName +} + +// NewOrUpdateDB 初始化或更新Gorm +func (c *Client) NewOrUpdateDB(dbname string) error { + var ( + orm *gorm.DB + err error + ) + + // first: open new gorm client + err = retry.Retry(func() error { + orm, err = openORM(dbname) + if err != nil { + xlog.Errorf("UpdateDB(%s) error:%+v", dbname, err) + return err + } + return nil + }, 5, 3*time.Second) + if err != nil { + return err + } + + // second: load gorm client + v, _ := c.maps.Load(dbname) + + // third: delete old gorm client and store the new gorm client + c.maps.Delete(dbname) + c.maps.Store(dbname, orm) + + // fourth: if old client is not nil, delete and close connection + if v != nil { + v.(*gorm.DB).Close() + } + return nil +} + +// GetORM 获取默认的Gorm实例 +// 目前仅支持 不传 或者仅传一个 dbname +func (c *Client) GetORM(dbname ...string) *gorm.DB { + name := c.defaultDbName + if len(dbname) == 1 { + name = dbname[0] + } + + v, ok := c.maps.Load(name) + if ok { + return v.(*gorm.DB) + } + return nil +} + +func (c *Client) Close() { + c.maps.Range(func(dbName, orm interface{}) bool { + xlog.Warnf("close db %s", dbName) + c.maps.Delete(dbName) + orm.(*gorm.DB).Close() + return true + }) +} + +func openORM(dbname string) (*gorm.DB, error) { + //默认配置 + viper.C.SetDefault(dbname, map[string]interface{}{ + "dbHost": "127.0.0.1", + "dbName": "phalgo", + "dbUser": "root", + "dbPasswd": "", + "dbPort": 3306, + "dbIdleconns_max": 20, + "dbOpenconns_max": 20, + "dbType": "mysql", + "dbDebug": false, + }) + dbHost := viper.GetEnvConfig(dbname + ".dbHost") + dbName := viper.GetEnvConfig(dbname + ".dbName") + dbUser := viper.GetEnvConfig(dbname + ".dbUser") + dbPasswd := viper.GetEnvConfig(dbname + ".dbPasswd") + dbPort := viper.GetEnvConfig(dbname + ".dbPort") + dbType := viper.GetEnvConfig(dbname + ".dbType") + dbDebug := viper.GetEnvConfigBool(dbname + ".dbDebug") + + connectString := dbUser + ":" + dbPasswd + "@tcp(" + dbHost + ":" + dbPort + ")/" + dbName + "?charset=utf8mb4&parseTime=true&loc=Local" + orm, err := gorm.Open(dbType, connectString) + if err != nil { + return nil, err + } + + // 连接池的空闲数大小 + orm.DB().SetMaxIdleConns(viper.C.GetInt(dbname + ".dbIdleconns_max")) + // 最大打开连接数 + orm.DB().SetMaxOpenConns(viper.C.GetInt(dbname + ".dbOpenconns_max")) + + if dbDebug { + // 开启Debug模式 + orm = orm.Debug() + } + return orm, nil +} diff --git a/gorm/gorm_test.go b/orm/gorm_test.go similarity index 93% rename from gorm/gorm_test.go rename to orm/gorm_test.go index 2edf274..bab018b 100644 --- a/gorm/gorm_test.go +++ b/orm/gorm_test.go @@ -1,4 +1,4 @@ -package gorm +package orm import ( "testing" diff --git a/gorm/model.go b/orm/model.go similarity index 98% rename from gorm/model.go rename to orm/model.go index b4b5b0d..fb86f89 100644 --- a/gorm/model.go +++ b/orm/model.go @@ -1,4 +1,4 @@ -package gorm +package orm import "github.com/jinzhu/gorm"