前言
关联的操作最重要的是many2many关系的维护
多对多关系模型创建
Many to Many 会在两个 model 中添加一张连接表。
type GirlGOD struct {
gorm.Model
Name string
Dogs []Dog `gorm:"many2many:dog_girl_tables"`
}
type Dog struct {
gorm.Model
Name string
GirlGODs []GirlGOD `gorm:"many2many:dog_girl_tables"`
Info Info
}
type Info struct {
gorm.Model
Age int
Money int
DogID uint
}
func main() {
db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
}
现在设置成dog1号舔狗舔2个女神,创建dog1的时候,会自动将其关联的girl,info,第三张中间表插入信息
func main() {
db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
g1 := GirlGOD{
Name: "girl1",
}
g2 := GirlGOD{
Name: "girl2",
}
info1 := Info{Money: 20000}
d1 := Dog{
Name: "dog1",
GirlGODs: []GirlGOD{g1, g2},
Info: info1,
}
db.Debug().Create(&d1)
}
2022/05/15 23:33:54 C:/Users/68725/Desktop/leetcode/main.go:42
[0.672ms] [rows:1] INSERT INTO `infos` (`created_at`,`updated_at`,`deleted_at`,`age`,`money`,`dog_id`) VALUES ('2022-05-15 23:33:54.308','2022-05-15 23:33:54.308',NULL,0,20000,1) ON DUPLICATE KEY UPDATE `dog_id`=VALUES(`dog_id`)
2022/05/15 23:33:54 C:/Users/68725/Desktop/leetcode/main.go:42
[0.593ms] [rows:2] INSERT INTO `girl_gods` (`created_at`,`updated_at`,`deleted_at`,`name`) VALUES ('2022-05-15 23:33:54.309','2022-05-15 23:33:54.309',NULL,'girl1'),('2022-05-15 23:33:54.309','2022-05-15 23:33:54.309',NULL,'girl2') ON DUPLICATE KEY UPDATE `id`=`id`
2022/05/15 23:33:54 C:/Users/68725/Desktop/leetcode/main.go:42
[0.516ms] [rows:2] INSERT INTO `dog_girl_tables` (`dog_id`,`girl_god_id`) VALUES (1,1),(1,2) ON DUPLICATE KEY UPDATE `dog_id`=`dog_id`
2022/05/15 23:33:54 C:/Users/68725/Desktop/leetcode/main.go:42
[43.094ms] [rows:1] INSERT INTO `dogs` (`created_at`,`updated_at`,`deleted_at`,`name`) VALUES ('2022-05-15 23:33:54.269','2022-05-15 23:33:54.269',NULL,'dog1')
再创建一个舔狗2号,舔1,2号女神。现在的关系是
func main() {
db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
g1 := GirlGOD{
Model: gorm.Model{ID: 1},
Name: "girl1",
}
g2 := GirlGOD{
Model: gorm.Model{ID: 2},
Name: "girl2",
}
info2 := Info{Money: 200}
d2 := Dog{
Name: "dog1",
GirlGODs: []GirlGOD{g1, g2},
Info: info2,
}
db.Debug().Create(&d2)
}
关联的操作
不用预加载
不用预加载可以发现只查询到了dog的信息,女神信息和info信息都没查出来
func main() {
db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
d := Dog{
Model: gorm.Model{ID: 1},
}
db.Debug().Find(&d)
fmt.Println(d)
}
2022/05/15 23:43:25 C:/Users/68725/Desktop/leetcode/main.go:34
[39.958ms] [rows:1] SELECT * FROM `dogs` WHERE `dogs`.`deleted_at` IS NULL AND `dogs`.`id` = 1
{{1 2022-05-15 23:39:58.732 +0800 CST 2022-05-15 23:39:58.732 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} dog1 [] {{0 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC {0001-01-01 00:00:00 +0000 UTC false}} 0 0 0}}
使用预加载
使用Preload发现会自动的从中间表中去加载女神信息
func main() {
db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
d := Dog{
Model: gorm.Model{ID: 1},
}
db.Debug().Preload("GirlGODs").Find(&d)
fmt.Println(d)
}
2022/05/15 23:45:07 C:/Users/68725/Desktop/leetcode/main.go:34
[2.252ms] [rows:2] SELECT * FROM `dog_girl_tables` WHERE `dog_girl_tables`.`dog_id` = 1
2022/05/15 23:45:07 C:/Users/68725/Desktop/leetcode/main.go:34
[0.517ms] [rows:2] SELECT * FROM `girl_gods` WHERE `girl_gods`.`id` IN (1,2) AND `girl_gods`.`deleted_at` IS NULL
2022/05/15 23:45:07 C:/Users/68725/Desktop/leetcode/main.go:34
[44.198ms] [rows:1] SELECT * FROM `dogs` WHERE `dogs`.`deleted_at` IS NULL AND `dogs`.`id` = 1
{{1 2022-05-15 23:39:58.732 +0800 CST 2022-05-15 23:39:58.732 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} dog1 [{{1 2022-05-15 23:39:58.782 +0800 CST 2022-05-15 23:39:58.782 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} girl1 []} {{2 2022-05-15 23:39:58.782 +0800 CST 2022-05-15 23:39:58.782 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} girl2 []}] {{0 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC {0001-01-01 00:00:00 +0000 UTC false}} 0 0 0}}
查找关联
只想通过舔狗查出女神,但是不想要舔狗的信息
func main() {
db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
d := Dog{
Model: gorm.Model{ID: 1},
}
var gs []GirlGOD
db.Debug().Model(&d).Association("GirlGODs").Find(&gs)
fmt.Println(gs)
}
[38.528ms] [rows:2] SELECT `girl_gods`.`id`,`girl_gods`.`created_at`,`girl_gods`.`updated_at`,`girl_gods`.`deleted_at`,`girl_gods`.`name` FROM `girl_gods` JOIN `dog_girl_tables` ON `dog_girl_tables`.`girl_god_id` = `girl_gods`.`id` AND `dog_girl_tables`.`dog_id` = 1 WHERE `girl_gods`.`deleted_at` IS NULL
[{{1 2022-05-15 23:39:58.782 +0800 CST 2022-05-15 23:39:58.782 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} girl1 []} {{2 2022-05-15 23:39:58.782 +0800 CST 2022-05-15 23:39:58.782 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} girl2 []}]
func main() {
db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
d := Dog{
Model: gorm.Model{ID: 1},
}
var gs []GirlGOD
db.Debug().Model(&d).Preload("Dogs").Association("GirlGODs").Find(&gs)
fmt.Println(gs)
}
只想通过舔狗查出女神,但是不想要舔狗的信息,但是又想要女神的舔狗的信息,这里Preload还可以后面跟条件,或者joins
2022/05/15 23:50:15 C:/Users/68725/Desktop/leetcode/main.go:35
[0.515ms] [rows:4] SELECT `dog_girl_tables`.`girl_god_id`,`dog_girl_tables`.`dog_id` FROM `dog_girl_tables` WHERE `dog_girl_tables`.`girl_god_id` IN (1,2)
2022/05/15 23:50:15 C:/Users/68725/Desktop/leetcode/main.go:35
[0.000ms] [rows:2] SELECT `dogs`.`id`,`dogs`.`created_at`,`dogs`.`updated_at`,`dogs`.`deleted_at`,`dogs`.`name` FROM `dogs` WHERE `dogs`.`id` IN (1,2) AND `dogs`.`deleted_at` IS NULL
2022/05/15 23:50:15 C:/Users/68725/Desktop/leetcode/main.go:35
[41.313ms] [rows:2] SELECT `girl_gods`.`id`,`girl_gods`.`created_at`,`girl_gods`.`updated_at`,`girl_gods`.`deleted_at`,`girl_gods`.`name` FROM `girl_gods` JOIN `dog_girl_tables` ON `dog_girl_tables`.`girl_god_id` = `girl_gods`.`id` AND `dog_girl_tables`.`dog_id` = 1 WHERE `girl_gods`.`deleted_at` IS NULL
[{{1 2022-05-15 23:39:58.782 +0800 CST 2022-05-15 23:39:58.782 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} girl1 [{{1 2022-05-15 23:39:58.732 +0800 CST 2022-05-15 23:39:58.732 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} dog1 [] {{0 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC {0001-01-01 00:00:00 +0000 UTC false}} 0 0 0}} {{2 2022-05-15 23:40:52.887 +0800 CST 2022-05-15 23:40:52.887 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} dog1 [] {{0 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC {0001-01-01 00:00:00 +0000 UTC false}} 0 0 0}}]} {{2 2022-05-15 23:39:58.782 +0800 CST 2022-05-15 23:39:58.782 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} girl2 [{{1 2022-05-15 23:39:58.732 +0800 CST 2022-05-15 23:39:58.732 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} dog1 [] {{0 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC {0001-01-01 00:00:00 +0000 UTC false}} 0 0 0}} {{2 2022-05-15 23:40:52.887 +0800 CST 2022-05-15 23:40:52.887 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} dog1 [] {{0 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC {0001-01-01 00:00:00 +0000 UTC false}} 0 0 0}}]}]
添加关联
跟dog3添加两个关联,发现中间表被自动维护了
func main() {
db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
d3 := Dog{
Name: "dog3",
}
g1 := GirlGOD{Model: gorm.Model{ID: 1}}
g2 := GirlGOD{Model: gorm.Model{ID: 2}}
db.Create(&d3)
db.Model(&d3).Association("GirlGODs").Append(&g1, &g2)
}
删除关联
func main() {
db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
d3 := Dog{
Model: gorm.Model{ID: 3},
}
g2 := GirlGOD{Model: gorm.Model{ID: 2}}
db.Debug().Model(&d3).Association("GirlGODs").Delete(&g2)
}
替换关联
替换关联会把当前所有的关系进行替换
func main() {
db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
db.AutoMigrate(&GirlGOD{}, &Dog{}, &Info{})
d3 := Dog{
Model: gorm.Model{ID: 3},
}
g2 := GirlGOD{Model: gorm.Model{ID: 2}}
db.Debug().Model(&d3).Association("GirlGODs").Replace(&g2)
}
g1 := GirlGOD{Model: gorm.Model{ID: 1}}
g2 := GirlGOD{Model: gorm.Model{ID: 2}}
db.Debug().Model(&d3).Association("GirlGODs").Replace(&g1, &g2)
清空关联
db.Debug().Model(&d3).Association("GirlGODs").Clear()
//[2.550ms] [rows:2] DELETE FROM `dog_girl_tables` WHERE `dog_girl_tables`.`dog_id` = 3