go語(yǔ)言中使用ent做關(guān)聯(lián)查詢(xún)的示例詳解
一、背景和意義
go語(yǔ)言的ent框架是facebook開(kāi)源的ORM框架,是go語(yǔ)言開(kāi)發(fā)中的常用框架,而關(guān)聯(lián)查詢(xún)又是日常開(kāi)發(fā)中的常見(jiàn)數(shù)據(jù)庫(kù)操作,故文本給出一個(gè)使用ent做關(guān)聯(lián)查詢(xún)的使用示例。
二、引入ent
安裝ent的命令為:
go install entgo.io/ent/cmd/ent@latest
找一個(gè)空目錄作為項(xiàng)目目錄,在目錄下執(zhí)行命令創(chuàng)建項(xiàng)目文件:
go mod init entdemo
執(zhí)行命令之后,項(xiàng)目下添加了go.mod文件。
三、定義數(shù)據(jù)庫(kù)實(shí)體
接下來(lái)創(chuàng)建ent數(shù)據(jù)庫(kù)實(shí)體文件,一個(gè)實(shí)體是學(xué)生(Student),一個(gè)實(shí)體是班級(jí)(Class),命令為:
ent new Class Student
執(zhí)行命令之后,項(xiàng)目下多了ent/schema/student.go和ent/schema/class.go兩個(gè)文件。我們準(zhǔn)備修改這兩個(gè)文件,修改前先添加相關(guān)依賴(lài):
go mod tidy
然后修改兩個(gè)文件的內(nèi)容,添加字段了關(guān)聯(lián)關(guān)系。
ent/schema/student.go:
package schema import ( "entgo.io/ent" "entgo.io/ent/schema/edge" "entgo.io/ent/schema/field" ) // Student holds the schema definition for the Student entity. type Student struct { ent.Schema } // Fields of the Student. func (Student) Fields() []ent.Field { return []ent.Field{ // 設(shè)置字段信息 field.String("name").MaxLen(50).Comment("名稱(chēng)"), field.Bool("sex").Comment("性別"), field.Int("age").Comment("年齡"), field.Int("class_id").Comment("班級(jí)ID"), } } // Edges of the Student. func (Student) Edges() []ent.Edge { return []ent.Edge{ // 設(shè)置關(guān)聯(lián)關(guān)系 edge.From("class", Class.Type). Ref("student"). Unique(). Field("class_id"). // 通過(guò)class_id字段關(guān)聯(lián)class表 Required(), } }
ent/schema/class.go:
package schema import ( "entgo.io/ent" "entgo.io/ent/schema/edge" "entgo.io/ent/schema/field" ) // Class holds the schema definition for the Class entity. type Class struct { ent.Schema } // Fields of the Class. func (Class) Fields() []ent.Field { return []ent.Field{ // 設(shè)置字段信息 field.String("name").MaxLen(50).Comment("名稱(chēng)"), field.Int("level").Comment("級(jí)別"), } } // Edges of the Class. func (Class) Edges() []ent.Edge { return []ent.Edge{ // 設(shè)置關(guān)聯(lián)關(guān)系 edge.To("student", Student.Type), // 表示一個(gè)班級(jí)可關(guān)聯(lián)多個(gè)學(xué)生 } }
其中student與class存在N對(duì)1的關(guān)聯(lián)關(guān)系,每個(gè)學(xué)生屬于某個(gè)班級(jí),一個(gè)班級(jí)可以包含多個(gè)學(xué)生,這一關(guān)聯(lián)信息體現(xiàn)在student.go和class.go中的Edges方法中。
接下來(lái)執(zhí)行命令:
go generate ./ent
執(zhí)行完之后,生成了ent相關(guān)的一些模板代碼。
四、創(chuàng)建表結(jié)構(gòu)
在項(xiàng)目下創(chuàng)建main.go文件:
package main import ( "context" "entdemo/ent" _ "github.com/go-sql-driver/mysql" "log" ) func main() { // 連接數(shù)據(jù)庫(kù), mysql連接串格式:username:password@(ipAddress)/databaseName?charset=utf8 URL := "test_user:123456@(127.0.0.1)/test?charset=utf8" client, err := ent.Open("mysql", URL) if err != nil { log.Fatalf("連接mysql數(shù)據(jù)庫(kù)失敗: %v", err) } defer client.Close() // 根據(jù)實(shí)體類(lèi)字段配置創(chuàng)建或更新數(shù)據(jù)庫(kù) ctx := context.Background() if err := client.Schema.Create(ctx); err != nil { log.Fatalf("創(chuàng)建數(shù)據(jù)結(jié)構(gòu)失敗: %v", err) } }
該文件中連接mysql數(shù)據(jù),然后調(diào)用ent.Client.Schama.Create方法創(chuàng)建數(shù)據(jù)表結(jié)構(gòu),執(zhí)行該文件程序之前,mysql數(shù)據(jù)中是這樣:
接下來(lái)執(zhí)行main.go:
go run main.go
執(zhí)行之后,程序創(chuàng)建了相關(guān)的數(shù)據(jù)表:
五、添加數(shù)據(jù)
創(chuàng)建create.go文件添加一些數(shù)據(jù):
package main import ( "context" "entdemo/ent" _ "github.com/go-sql-driver/mysql" "log" ) func main() { // 連接數(shù)據(jù)庫(kù), mysql連接串格式:username:password@(ipAddress)/databaseName?charset=utf8 URL := "test_user:123456@(127.0.0.1)/test?charset=utf8" client, err := ent.Open("mysql", URL) if err != nil { log.Fatalf("連接mysql數(shù)據(jù)庫(kù)失敗: %v", err) } defer client.Close() ctx := context.Background() // 創(chuàng)建班級(jí) class3, err := client.Class.Create().SetName("三班").SetLevel(5).Save(ctx) if err != nil { log.Fatalf("創(chuàng)建班級(jí)失敗:%v", err) return } class2, err := client.Class.Create().SetName("二班").SetLevel(6).Save(ctx) if err != nil { log.Fatalf("創(chuàng)建班級(jí)失?。?v", err) return } // 創(chuàng)建學(xué)生 u1, err := client.Student.Create(). SetClass(class3).SetName("小張").SetSex(false).SetAge(12).Save(ctx) if err != nil { log.Fatalf("創(chuàng)建用戶(hù)失?。?v", err) return } log.Println("創(chuàng)建用戶(hù):", u1) u2, err := client.Student.Create(). SetClass(class3).SetName("小李").SetSex(true).SetAge(11).Save(ctx) if err != nil { log.Fatalf("創(chuàng)建用戶(hù)失敗:%v", err) return } log.Println("創(chuàng)建用戶(hù):", u2) u3, err := client.Student.Create(). SetClass(class2).SetName("小趙").SetSex(true).SetAge(12).Save(ctx) if err != nil { log.Fatalf("創(chuàng)建用戶(hù)失?。?v", err) return } log.Println("創(chuàng)建用戶(hù):", u3) }
這里需要注意的是,學(xué)生和班級(jí)之間存在關(guān)聯(lián)關(guān)系,這里是在學(xué)生側(cè)調(diào)用SetClass方法設(shè)置當(dāng)前學(xué)生所關(guān)聯(lián)的班級(jí)實(shí)體。
接下來(lái)執(zhí)行命令:
go run create.go
執(zhí)行完之后,查數(shù)據(jù)庫(kù),可以看到students和classes表增加了一些數(shù)據(jù)。
六、查詢(xún)數(shù)據(jù)
創(chuàng)建文件query.go:
package main import ( "context" "entdemo/ent" _ "github.com/go-sql-driver/mysql" "log" ) func main() { // 連接數(shù)據(jù)庫(kù), mysql連接串格式:username:password@(ipAddress)/databaseName?charset=utf8 URL := "test_user:123456@(127.0.0.1)/test?charset=utf8" client, err := ent.Open("mysql", URL) if err != nil { log.Fatalf("連接mysql數(shù)據(jù)庫(kù)失敗: %v", err) } defer client.Close() ctx := context.Background() uList, err := client.Student.Query().WithClass().All(ctx) if err != nil { log.Fatalf("查詢(xún)數(shù)據(jù)失?。?v", err) return } for _, v := range uList { log.Println("學(xué)生:", v, ",所在班級(jí):", v.Edges.Class) } }
這里需要注意的是,如果我們既要獲取學(xué)生數(shù)據(jù),又要獲取每個(gè)學(xué)生所在班級(jí)的信息,那么需要關(guān)聯(lián)查詢(xún)students和classes表,代碼中是通過(guò)調(diào)用WithClass()
方法實(shí)現(xiàn)的。在做關(guān)聯(lián)查詢(xún)之后,班級(jí)信息會(huì)存儲(chǔ)在Student實(shí)體的Edges.Class
屬性中。
運(yùn)行命令:
go run query.go
終端將輸出如下執(zhí)行結(jié)果:
以上就是go語(yǔ)言中使用ent做關(guān)聯(lián)查詢(xún)的示例詳解的詳細(xì)內(nèi)容,更多關(guān)于go ent關(guān)聯(lián)查詢(xún)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解決golang在import自己的包報(bào)錯(cuò)的問(wèn)題
這篇文章主要介紹了解決golang在import自己的包報(bào)錯(cuò)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04Golang?統(tǒng)計(jì)字符串中數(shù)字字母數(shù)量的實(shí)現(xiàn)方法
這篇文章主要介紹了Golang?統(tǒng)計(jì)字符串中數(shù)字字母數(shù)量,本文給出了兩種從字符串獲取數(shù)字與字母數(shù)量的方法,分別是ASCII 碼值和正則表達(dá)式,需要的朋友可以參考下2022-06-06探索Golang實(shí)現(xiàn)Redis持久化AOF實(shí)例
這篇文章主要為大家介紹了Golang實(shí)現(xiàn)Redis持久化AOF實(shí)例探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01Golang使用crypto/ed25519實(shí)現(xiàn)數(shù)字簽名和驗(yàn)證
本文將深入探討如何在?Golang?中使用?crypto/ed25519?進(jìn)行數(shù)字簽名和驗(yàn)證,我們將從基本原理開(kāi)始,逐步引導(dǎo)讀者了解生成密鑰對(duì)、進(jìn)行數(shù)字簽名,以及驗(yàn)證簽名的具體過(guò)程,希望對(duì)大家有所幫助2024-02-02