Many To Many(多对多)

如果你一对多关系搞懂了的话,多对多其实也很容易

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type Student struct {
Id int
Name string

// many2many
Teachers []Teacher `gorm:"many2many:student_teachers;"`
}

type Teacher struct {
Id int
Name string

// many2many
Students []Student `gorm:"many2many:student_teachers"`
}

就是互相放对方的切片嘛,但是这个关系交给一个第三方表来记录,所以需要加一个 tag

然后建表,可以看见建了三个表

1
GLOBAL_DB.AutoMigrate(&Student{}, &Teacher{})

image-20221007100441964

创建

这个应该很简单了

1
2
3
4
5
6
7
teacher1 := Teacher{Name: "teacher1"}
teacher2 := Teacher{Name: "teacher2"}
student1 := Student{
Name: "student1",
Teachers: []Teacher{teacher1, teacher2},
}
GLOBAL_DB.Create(&student1)

image-20221007101557255

可见二者的关系是靠一个中间表来维护的


查询

这个还不是预加载那一套?其实和上一节差不多的

1
2
3
var result = Student{Id: 1}
GLOBAL_DB.Preload("Teachers").Find(&result)
fmt.Println(result)

image-20221007102048058

但是有时候结果只需要一个 teacher 的切片,这时候怎么办?

可以使用配合 Association()

1
2
3
4
var student = Student{Id: 1}
var result []Teacher
GLOBAL_DB.Model(&student).Association("Teachers").Find(&result)
fmt.Println(result)

image-20221007103548000

这个时候还想把 teacher 里面的学生也带出来怎么办?用预加载

1
GLOBAL_DB.Model(&student).Preload("Students").Association("Teachers").Find(&result)

image-20221007103733075

(当然你还可以套娃下去)

如果还有子模型,还可以结合上节的 Joins ,等等

这些和之前的是一样的,还有什么关系的维护方法也是和之前一样的

只是存储的结构变了而已