GORM 入门笔记(七)一对多关联(Has Many)与进阶预加载
Has Many(一对多)
先回忆一下 Has One 的表达
1 | type Student struct { |
然后现在是 Has Many 嘛,一个 teacher 必定不止有一个 student
所以 Student 应该是一个切片
1 | type Student struct { |
然后创建表
1 | GLOBAL_DB.AutoMigrate(&Student{}, &Teacher{}) |
可以看见,数据库中的结构与 Has One 的是一样的
也不难理解,Has Many 只是能让多个学生指向同一个老师而已
创建
现在尝试一下使用 Has Many 的创建
1 | student1 := Student{Name: "student1"} |
可以看见两个学生都指向了同一个老师,这就是 Has Many
查询
如果你直接查询老师的话,你会发现没有学生的信息
1 | var result Teacher |
为什么呢?因为没有预加载
1 | GLOBAL_DB.Preload("Student").First(&result) |
这样就可以了
预加载的进阶使用
条件预加载
那么如果需要筛选一下呢?比如只想带出第一个学生
可以直接在预加载函数中添加条件
1 | GLOBAL_DB.Preload("Student", "name = ?", "student1").First(&result) |
自定义预加载 SQL
这只是简单场景,如果是要复杂的过滤呢?
或者像官网上一样搞排序什么的(
那就要使用自定义的函数了
1 | GLOBAL_DB.Preload("Student", func(db *gorm.DB) *gorm.DB { |
这个函数里面可以塞很多东西
链式预加载
关系很可能不止一层,现在给学生拥有一个 Info 模型,里面有学生的成绩
(当然这只是为了举例子,别杠为什么不直接写在 Student 里面)
1 | type Info struct { |
然后创建
1 | GLOBAL_DB.AutoMigrate(&Student{}, &Teacher{}, &Info{}) |
这里为了省事就直接往里面塞数据了
尝试刚才的查询,你会发现成绩并没有被带出来
1 | var result Teacher |
应该使用链式结构
1 | GLOBAL_DB.Preload("Student.Info").First(&result) |
但是这里就有一个问题需要说明,就是要怎么添加条件
例如条件还是和上面一样,只要第一个学生,正确的写法应当是这样
1 | GLOBAL_DB.Preload("Student.Info").Preload("Student", "name = ?", "student1").First(&result) |
也就是说,每层的预加载只能决定你当前层的数据能不能被带出来
例如这样
1 | GLOBAL_DB.Preload("Student.Info", "score > 60").First(&result) |
你会看见两个人都被查出来了,但是不及格的成绩没有被带出来
查询条件只适用于当前加载的那一层
Joins()
预加载
上面的那条看上去只会查到及格的学生,但其实并不是
那如果我就想要及格的学生,没及格的我看都不想看见呢?
这可以使用自定义函数 + Joins()
1 | GLOBAL_DB.Preload("Student", func(db *gorm.DB) *gorm.DB { |
这东西常用的就是这样,详细的可以去官网看看
评论
GiscusTwikoo