欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

golang?gorm學(xué)習(xí)之如何指定數(shù)據(jù)表

 更新時間:2023年08月24日 09:07:07   作者:Go學(xué)堂  
在sql中首先要指定是從哪張表中查詢,所以這篇文章小編就來帶大家一起看一下gorm是如何根據(jù)model來自動解析表名的,感興趣的小伙伴可以了解下

一、通過model名稱自動匹配表名

我們看如下例子:

type MTest struct {
	Id int64
	Name string
}
func main() {
	dsn := "test:123456@tcp(localhlost:3306)/test01?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"
	db, _ := gorm.Open(mysql.Open(dsn))
	m := MTest{}
	db.Find(m)
	fmt.Println(m)
	fmt.Println(db.Statement.Table)
}

在這個例子中,表名是通過根據(jù)model的結(jié)構(gòu)體的名字MTest來指定的。規(guī)則如下:

  • 若是駝峰的形式,則兩個大小字母之間會加一個下劃線連接。
  • 是結(jié)構(gòu)體名稱的復(fù)數(shù)形式。復(fù)數(shù)形式符合英文單詞的復(fù)數(shù)規(guī)則。例如若最后一個單詞是s,那么最終表名就不會再加s。比如model結(jié)構(gòu)體的名稱是a01s,那么最終的表名就是a01s。

所以,上面的表名最終是:m_tests

這種方式的實現(xiàn),本質(zhì)上是通過gorm.Open中指定的名稱策略來實現(xiàn)的。如下:

在NamingStrategy結(jié)構(gòu)體中,可以指定前綴以及是否是復(fù)數(shù)形式,如下:

func (ns NamingStrategy) TableName(str string) string {
	if ns.SingularTable {
		return ns.TablePrefix + ns.toDBName(str)
	}
	return ns.TablePrefix + inflection.Plural(ns.toDBName(str))
}

指定表前綴、禁用復(fù)數(shù)

通過在gorm.Open的函數(shù)中指定對應(yīng)的配置選項,就可以給本次連接做相關(guān)的配置。比如指定表名前綴,禁用表名復(fù)數(shù)等。如下:

type MTest struct {
	Id int64
	Name string
}
func main() {
	dsn := "sands:123456@tcp(test.trdplace.ads.sg1.mysql:3306)/test01?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"
	config := &gorm.Config{
		NamingStrategy: schema.NamingStrategy{
			TablePrefix:   "pre_",   // 表前綴
			SingularTable: true, // 禁用表名復(fù)數(shù)
		}}
	db, _ := gorm.Open(mysql.Open(dsn), config)
	m := MTest{}
	db.Find(m)
	fmt.Println(m)
	fmt.Println(db.Statement.Table)
}

如上,最終打印出的表名就是m_test

二、通過實現(xiàn)Tabler接口指定表名

第二種方式是通過讓model結(jié)構(gòu)體實現(xiàn)TableName() string 函數(shù)來指定具體的表名。如下:

type MTest struct {
	Id int64
	Name string
}
func (m *MTest) TableName() string {
    return "m_test"
}

這樣,表名就是TableName指定的字符串,指定什么就是什么。其實這個本質(zhì)上是實現(xiàn)了Tabler接口:

type Tabler interface {
	TableName() string
}

三、通過實現(xiàn)TablerWithNamer接口指定表名

第三種方式是讓Model結(jié)構(gòu)體實現(xiàn)TablerWithNamer接口來指定表名。接口定義如下:

type TablerWithNamer interface {
	TableName(Namer) string
}

這里的Namer也是一個接口,在第一種方式中,實際上就是指定了一個Namer,在gorm.Open函數(shù)中,我們看下:

當(dāng)然,我們也可以自己實現(xiàn)Namer接口來指定具體的表名規(guī)則。

四、通過embeddedNamer結(jié)構(gòu)體

這個是在Namer接口的基礎(chǔ)上,如果該Namer是embeddedNamer結(jié)構(gòu)體類型,那么優(yōu)先使用這個結(jié)構(gòu)體中指定的名稱。embeddedNamer結(jié)構(gòu)體如下:

type embeddedNamer struct {
	Table string
	Namer
}

五、查詢時直接通過db.Table函數(shù)指定表名

使用db.Table指定的表后,gorm將不再使用自動解析出來的表名了。所以該方式的優(yōu)先級是最高的。如下:

type MTest struct {
	Id int64
	Name string
}
func main() {
	dsn := "123456:123456@tcp(localhost:3306)/test01?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms"
	db, _ := gorm.Open(mysql.Open(dsn))
	m := MTest{}
	db.Table("m_tests").Find(m)
}

六、實現(xiàn)原理

還是以db.Find(m)為例。 首先,F(xiàn)ind函數(shù)會把m對象賦值給db.Statement.Dest字段。這個Dest字段就是要查詢的目標(biāo)數(shù)據(jù)。然后再調(diào)用db.callbacks.Query().Execute(tx)。就是實際的查詢函數(shù)。如下是db.Find的代碼:

func (db *DB) Find(dest interface{}, conds ...interface{}) (tx *DB) {
	tx = db.getInstance()
	if len(conds) > 0 {
		if exprs := tx.Statement.BuildCondition(conds[0], conds[1:]...); len(exprs) > 0 {
			tx.Statement.AddClause(clause.Where{Exprs: exprs})
		}
	}
	tx.Statement.Dest = dest
	return tx.callbacks.Query().Execute(tx)
}

其中tx是從原db中再獲取一個db對象,同時也具有了對應(yīng)的數(shù)據(jù)庫連接的對象。然后tx.callbacks.Query()其實就是db.Open函數(shù)中初始化的callbacks:db.callbacks = initializeCallbacks(db)。如下:

func initializeCallbacks(db *DB) *callbacks {
	return &callbacks{
		processors: map[string]*processor{
			"create": {db: db},
			"query":  {db: db},
			"update": {db: db},
			"delete": {db: db},
			"row":    {db: db},
			"raw":    {db: db},
		},
	}
}

其次,在processor.Execute函數(shù)中會看到,statement.Model和statement.Dest會相互賦值。如下:

最主要的是在statement.Parse函數(shù)解析的表名了。依次看代碼調(diào)用,最終會到schema.go文件中的ParseWithSpecialTableName函數(shù)中,在這個函數(shù)中,有對表名的解析。如下:

七、總結(jié)

本文總結(jié)了gorm中如何指定表名的多種方式。其中優(yōu)先級最高的是通過gorm會根據(jù)指定的model結(jié)構(gòu)體的名稱自動解析出表名。同時,如果model實現(xiàn)了Tabler接口或TablerWithNamer接口,那么就會優(yōu)先根據(jù)這兩個接口的對應(yīng)TableName函數(shù)指定的表名進行解析。

以上就是golang gorm學(xué)習(xí)之如何指定數(shù)據(jù)表的詳細(xì)內(nèi)容,更多關(guān)于gorm指定數(shù)據(jù)表的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go語言Gin框架實現(xiàn)HTML頁面渲染

    Go語言Gin框架實現(xiàn)HTML頁面渲染

    Web開發(fā)中,我們經(jīng)常要面對如何將數(shù)據(jù)渲染到前端的問題,這就涉及到了模板引擎的知識,Go語言的Gin框架就提供了強大的HTML模板渲染功能,本文就來為大家介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2024-01-01
  • GO必知必會的常見面試題匯總

    GO必知必會的常見面試題匯總

    這篇文章主要為大家介紹了GO必知必會的常見面試題匯總
    2022-08-08
  • golang定時器Timer的用法和實現(xiàn)原理解析

    golang定時器Timer的用法和實現(xiàn)原理解析

    這篇文章主要介紹了golang定時器Ticker,本文主要來看一下Timer的用法和實現(xiàn)原理,需要的朋友可以參考以下內(nèi)容
    2023-04-04
  • Go語言范圍Range的具體使用

    Go語言范圍Range的具體使用

    range關(guān)鍵字在for循環(huán)中用于遍歷數(shù)組,切片,通道或映射的項目,本文主要介紹了Go語言范圍Range的具體使用,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • Golang函數(shù)這些神操作你知道哪些

    Golang函數(shù)這些神操作你知道哪些

    這篇文章主要為大家介紹了一些Golang中函數(shù)的神操作,不知道你都知道哪些呢?文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,需要的可以參考一下
    2023-02-02
  • GO 語言學(xué)習(xí)指南

    GO 語言學(xué)習(xí)指南

    這篇文章主要介紹了GO 語言學(xué)習(xí)指南,介紹的相當(dāng)全面,有需要的小伙伴參考下吧。
    2015-01-01
  • 詳解Golang語言HTTP客戶端實踐

    詳解Golang語言HTTP客戶端實踐

    本文主要介紹了Golang語言HTTP客戶端實踐,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • Go語言struct類型介紹

    Go語言struct類型介紹

    這篇文章主要介紹了Go語言struct類型介紹,本文講解了struct的2種聲明方式,struct的匿名字段等內(nèi)容,需要的朋友可以參考下
    2015-01-01
  • Go語言學(xué)習(xí)之循環(huán)語句使用詳解

    Go語言學(xué)習(xí)之循環(huán)語句使用詳解

    這篇文章主要為大家介紹了Go語言中的常用循環(huán)語句的使用,例如:for循環(huán)、for-each、break等,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2022-04-04
  • Golang?gRPC?HTTP協(xié)議轉(zhuǎn)換示例

    Golang?gRPC?HTTP協(xié)議轉(zhuǎn)換示例

    這篇文章主要為大家介紹了Golang?gRPC?HTTP協(xié)議轉(zhuǎn)換示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06

最新評論