阿里云虛擬主機(jī)怎么建設(shè)網(wǎng)站seopeix
GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.
一 對(duì)多入門
比如要開發(fā)cmdb的系統(tǒng),無(wú)論是硬件還是軟件。硬件對(duì)應(yīng)的就是對(duì)應(yīng)的哪個(gè)開發(fā)在用?;蛘叻?wù)對(duì)應(yīng)的是哪個(gè)業(yè)務(wù)模塊在使用,或者應(yīng)用誰(shuí)在使用。那么這就是一對(duì)多的關(guān)系。
has many介紹
- has many 關(guān)聯(lián)就是創(chuàng)建和另一個(gè)模型的一對(duì)多關(guān)系(數(shù)據(jù)庫(kù)里面是一對(duì)多,然后struct里面也是一對(duì)多)
- 例如, 例如每一個(gè)用戶都擁有多張信用卡,這樣就是生活中一個(gè)簡(jiǎn)單的一對(duì)多關(guān)系
在設(shè)計(jì)表的時(shí)候不可能將所有的信息都放在一個(gè)表里面,那么表就會(huì)非常非常的寬。這樣字段就會(huì)非常的多,性能就會(huì)受到影響。
在設(shè)計(jì)的時(shí)候這里其實(shí)就可以設(shè)置為兩張表。一個(gè)是用戶的詳情表和信用卡的詳情表,用戶表里面加上卡的id和他做一個(gè)關(guān)聯(lián),那么這就是一對(duì)多的關(guān)系。
當(dāng)一個(gè)數(shù)據(jù)庫(kù)存儲(chǔ)了很多數(shù)據(jù)的時(shí)候就需要分庫(kù)分表,上面也類似,將一張表分為兩張表。
creditcar的外鍵是userid。
package mainimport ("gorm.io/driver/mysql""gorm.io/gorm"
)type User struct {gorm.Model //默認(rèn)創(chuàng)建三個(gè)時(shí)間字段和一個(gè)id字段,create_at update_at delete_at這樣可以知道創(chuàng)建時(shí)間/更新時(shí)間/刪除時(shí)間CreditCards []*CreditCard66
}//用戶有多張信用卡,UserID是外鍵
type CreditCard struct {gorm.ModelNumber stringUserId int //默認(rèn)會(huì)在CreditCard表中生成User66Id字段作為與user表關(guān)聯(lián)的外鍵id//默認(rèn)會(huì)在CreditCard表中生成UserID字段作為與User表關(guān)聯(lián)的外鍵ID
}func main() {dsn := "root:7PXjAkY!&nlR@tcp(192.168.11.128:3306)/test_db?charset=utf8mb4&parseTime=True&loc=Local"db, _ := gorm.Open(mysql.Open(dsn66), &gorm.Config{})db.AutoMigrate(User{}, CreditCard{})
}
mysql> show tables;
+-------------------+
| Tables_in_test_db |
+-------------------+
| credit_cards |
| users |
+-------------------+
2 rows in set (0.00 sec)mysql> desc users;
+------------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-----------------+------+-----+---------+----------------+
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| created_at | datetime(3) | YES | | NULL | |
| updated_at | datetime(3) | YES | | NULL | |
| deleted_at | datetime(3) | YES | MUL | NULL | |
+------------+-----------------+------+-----+---------+----------------+mysql> desc credit_cards;
+------------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-----------------+------+-----+---------+----------------+
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| created_at | datetime(3) | YES | | NULL | |
| updated_at | datetime(3) | YES | | NULL | |
| deleted_at | datetime(3) | YES | MUL | NULL | |
| number | bigint | YES | | NULL | |
| user_id | bigint unsigned | YES | MUL | NULL | |
+------------+-----------------+------+-----+---------+----------------+mysql> drop table users;
ERROR 3730 (HY000): Cannot drop table 'users' referenced by a foreign key constraint 'fk_users_credit_cards' on table 'credit_cards'.
?二? 外鍵
type User struct{gorm.ModelCreditCards []CreditCard `gorm:"foreignKey:UserRefer"`
}type CreditCard struct{gorm.ModelNumber??stringUserRefer uint
}
`gorm:"foreignKey:UserRefer"` 可以使用這個(gè)字段來(lái)去改它的外鍵。
import ("gorm.io/driver/mysql""gorm.io/gorm"
)type User struct {gorm.ModelCreditCards []*CreditCard `gorm:"foreignKey:UserRefer"`
}type CreditCard struct {gorm.ModelNumber intUserRefer int
}func main() {dsn6 := "root:7PXjAkY!&nlR@tcp(192.168.11.128:3306)/test_db?charset=utf8mb4&parseTime=True&loc=Local"db, _ := gorm.Open(mysql.Open(dsn6), &gorm.Config{})db.AutoMigrate(&User{}, &CreditCard{})
}mysql> desc users;
+------------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-----------------+------+-----+---------+----------------+
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| created_at | datetime(3) | YES | | NULL | |
| updated_at | datetime(3) | YES | | NULL | |
| deleted_at | datetime(3) | YES | MUL | NULL | |
+------------+-----------------+------+-----+---------+----------------+mysql> desc credit_cards;
+------------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-----------------+------+-----+---------+----------------+
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| created_at | datetime(3) | YES | | NULL | |
| updated_at | datetime(3) | YES | | NULL | |
| deleted_at | datetime(3) | YES | MUL | NULL | |
| number | bigint | YES | | NULL | |
| user_refer | bigint unsigned | YES | MUL | NULL | |
+------------+-----------------+------+-----+---------+----------------+mysql> drop tables users;
ERROR 3730 (HY000): Cannot drop table 'users' referenced by a foreign key constraint 'fk_users_credit_cards' on table 'credit_cards'.
一般不推薦使用這種方式,還是推薦使用Userid的方式。
三 外鍵關(guān)聯(lián)
type User struct {gorm.ModelMemberNumber string
// 默認(rèn)CreditCard會(huì)使用User表的Id作為外鍵,association_foreignkey:MemberNumber
// 指定使用MemberNumber 作為外鍵關(guān)聯(lián)
CreditCards []CreditCard
`gorm:"foreignkey:UserMemberNumber;association_foreignkey:MemberNumber"`
}type CreditCard struct {gorm.ModelNumber stringUserMemberNumber string
}
其實(shí)就是creditcard外鍵UserMemberNumber直接去找user的?MemberNumber。
上面其實(shí)也就是改變了外鍵的默認(rèn)值,默認(rèn)外鍵是Userid,那么現(xiàn)在變?yōu)榱薓emberNumber。
一般使用默認(rèn)id的外鍵就能夠覆蓋很多場(chǎng)景,上面這種只是舉例。
package mainimport ("gorm.io/driver/mysql""gorm.io/gorm"
)type User struct {gorm.ModelMemberNumber stringCreditCards []*CreditCard `gorm:"foreignKey:UserMemberNumber;association_foreignKey:MemberNumber"`
}type CreditCard struct {gorm.ModelNumber intUserMemberNumber string
}func main() {dsn6 := "root:7PXjAkY!&nlR@tcp(192.168.11.128:3306)/test_db?charset=utf8mb4&parseTime=True&loc=Local"db, _ := gorm.Open(mysql.Open(dsn6), &gorm.Config{})db.AutoMigrate(&User{}, &CreditCard{})
}mysql> desc users;
+---------------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+-----------------+------+-----+---------+----------------+
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| created_at | datetime(3) | YES | | NULL | |
| updated_at | datetime(3) | YES | | NULL | |
| deleted_at | datetime(3) | YES | MUL | NULL | |
| member_number | longtext | YES | | NULL | |
+---------------+-----------------+------+-----+---------+----------------+mysql> desc credit_cards;
+--------------------+-----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+-----------------+------+-----+---------+----------------+
| id | bigint unsigned | NO | PRI | NULL | auto_increment |
| created_at | datetime(3) | YES | | NULL | |
| updated_at | datetime(3) | YES | | NULL | |
| deleted_at | datetime(3) | YES | MUL | NULL | |
| number | bigint | YES | | NULL | |
| user_member_number | bigint unsigned | YES | MUL | NULL | |
+--------------------+-----------------+------+-----+---------+----------------+
四 創(chuàng)建一對(duì)多表
/*
constraint:OnUpdate:CASCADE 【當(dāng)User表更新,也會(huì)同步給CreditCards】 // 外鍵約束
OnDelete:SET NULL 【當(dāng)User中數(shù)據(jù)被刪除時(shí),CreditCard關(guān)聯(lián)設(shè)置為 NULL,不刪除記錄】
*/type User struct {gorm.ModelUsername string `json:"username" gorm:"column:username"`CreditCards []CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}type CreditCard struct {gorm.ModelNumber stringUserID uint
}func main() {// 0、連接數(shù)據(jù)庫(kù)dsn := "root:1@tcp(127.0.0.1:3306)/test_db?charset=utf8mb4&parseTime=True&loc=Local"db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})// 創(chuàng)建表結(jié)構(gòu)db.AutoMigrate(User{}, CreditCard{})// 1、創(chuàng)建一對(duì)多user := User{Username: "zhangsan",CreditCards: []CreditCard{{Number: "0001"},{Number: "0002"},},
}db.Create(&user)// 2、為已存在用戶添加信用卡u := User{Username: "zhangsan"}db.First(&u)//fmt.Println(u.Username)}
3. 一對(duì)多Association 查找關(guān)聯(lián) 使用 Association 方法, 需要把把 User 查詢好, 然后根據(jù) User 定義中指定的 AssociationForeignKey 去查找 CreditCard
import ("fmt""gorm.io/driver/mysql""gorm.io/gorm"
)type User struct {gorm.ModelUserName string `json:"username" gorm:"column:username"`CreditCards []CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}type CreditCard struct {gorm.ModelNumber stringUserID int
}func main() {dsn6 := "root:7PXjAkY!&nlR@tcp(192.168.11.128:3306)/test_db?charset=utf8mb4&parseTime=True&loc=Local"db, _ := gorm.Open(mysql.Open(dsn6), &gorm.Config{})db.AutoMigrate(&User{}, &CreditCard{})/*u := &User{Model: gorm.Model{},UserName: "lucas",CreditCards: []*CreditCard{{Number: "0001", UserID: 1},{Number: "0002", UserID: 2},},}db.Create(u)*/// 1、查找 用戶名為 lucas 的所有信用卡信息u1 := &User{UserName: "lucas"}// Association必須要先查出User才能關(guān)聯(lián)查詢對(duì)應(yīng)的CreditCarddb.First(u1)db.Model(u1).Association("CreditCards").Find(&u1.CreditCards)fmt.Println(u1)}
追加
package mainimport ("encoding/json""fmt""gorm.io/driver/mysql""gorm.io/gorm"
)type User struct {gorm.ModelUserName string `json:"username" gorm:"column:username"`CreditCards []CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}type CreditCard struct {gorm.ModelNumber stringUserID int
}func main() {dsn6 := "root:7PXjAkY!&nlR@tcp(192.168.11.128:3306)/test_db?charset=utf8mb4&parseTime=True&loc=Local"db, _ := gorm.Open(mysql.Open(dsn6), &gorm.Config{})db.AutoMigrate(&User{}, &CreditCard{})u := &User{Model: gorm.Model{},UserName: "lucas",CreditCards: []CreditCard{{Number: "0001", UserID: 0},{Number: "0002", UserID: 1},},}db.Create(u)u1 := &User{UserName: "lucas"}db.First(u1)db.Model(u1).Association("CreditCards").Find(&u1.CreditCards)fmt.Println(u1)db.Model(u1).Association("CreditCards").Append([]CreditCard{{Number: "0008", UserID: 1},})fmt.Println(u1)strUser, _ := json.Marshal(u1)fmt.Println(string(strUser))
}&{{1 2023-04-16 10:48:54.423 +0800 CST 2023-04-16 14:12:45.825 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} lucas []}&{{1 2023-04-16 10:48:54.423 +0800 CST 2023-04-16 14:15:51.44 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} lucas [{{17 2023-04-16 14:15:51.445+0800 CST 2023-04-16 14:15:51.445 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} 0008 1}]}{"ID":1,"CreatedAt":"2023-04-16T10:48:54.423+08:00","UpdatedAt":"2023-04-16T14:15:51.44+08:00","DeletedAt":null,"username":"lucas","CreditCards":[
{"ID":17,"CreatedAt":"2023-04-16T14:15:51.445+08:00","UpdatedAt":"2023-04-16T14:15:51.445+08:00","DeletedAt":null,"Number":"0008","UserID":1}]}
?
?
4. 一對(duì)多Preload 預(yù)加載
使用 Preload 方法, 在查詢 User 時(shí)先去獲取 CreditCard 的記錄
和上面associate不一樣,他們兩個(gè)最大的區(qū)別是執(zhí)行的順序是不一樣的,associate是先去獲取user,再去獲取creditcard。
preload是先去獲取creditcard,再去獲取user。
package main
import (
"encoding/json"
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
/*
constraint:OnUpdate:CASCADE 【當(dāng)User表更新,也會(huì)同步給CreditCards】
OnDelete:SET NULL 【當(dāng)User中數(shù)據(jù)被刪除時(shí),CreditCard關(guān)聯(lián)設(shè)置為 NULL,不刪除記錄】
*/
type User struct {
gorm.Model
Username string `json:"username" gorm:"column:username"`
CreditCards []CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET
NULL;"`
}
type CreditCard struct {
gorm.Model
Number string
UserID uint
}
func main() {
// 0、連接數(shù)據(jù)庫(kù)
dsn := "root:1@tcp(127.0.0.1:3306)/test_db?
charset=utf8mb4&parseTime=True&loc=Local"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// 1、預(yù)加載: 查找 user 時(shí)預(yù)加載相關(guān) CreditCards
//users := User{Username: "zhangsan"} // 只查找張三用戶的信用卡信息
users := []User{}
db.Preload("CreditCards").Find(&users)
查詢結(jié)果[
{
"ID":1,
"username":"zhangsan",
"CreditCards":[
{
"ID":1,
"Number":"0001",
"UserID":1
},
...
]
}
]