[ go 与 golang | 青训营笔记]
这是我参与「第五届青训营 」伴学笔记创作活动的第 16 天, 在学习了go的相关基础知识以后,可以说是初步的了解了go,接下来,我们将步入全新的环节,今天我们学习go的一个常用orm框架gorm
6.高级查询-升级
子查询
查询大于平均年龄的用户
# 原生sql
select * from students where age > (select avg(age) from students);
使用gorm编写
var users []Student
DB.Model(Student{}).Where("age > (?)", DB.Model(Student{}).Select("avg(age)")).Find(&users)
fmt.Println(users)
命名参数
var users []Student
DB.Where("name = @name and age = @age", sql.Named("name", "枫枫"), sql.Named("age", 23)).Find(&users)
DB.Where("name = @name and age = @age", map[string]any{"name": "枫枫", "age": 23}).Find(&users)
fmt.Println(users)
find到map
var res []map[string]any
DB.Table("students").Find(&res)
fmt.Println(res)
查询引用Scope
可以再model层写一些通用的查询方式,这样外界就可以直接调用方法即可
func Age23(db *gorm.DB) *gorm.DB {
return db.Where("age > ?", 23)
}
func main(){
var users []Student
DB.Scopes(Age23).Find(&users)
fmt.Println(users)
}
7. 一对一关系
一对一关系比较少,一般用于表的扩展
例如一张用户表,有很多字段
那么就可以把它拆分为两张表,常用的字段放主表,不常用的字段放详情表
表结构搭建
type User struct {
ID uint
Name string
Age int
Gender bool
UserInfo UserInfo // 通过UserInfo可以拿到用户详情信息
}
type UserInfo struct {
UserID uint // 外键
ID uint
Addr string
Like string
}
添加记录
添加用户,自动添加用户详情
DB.Create(&User{
Name: "枫枫",
Age: 21,
Gender: true,
UserInfo: UserInfo{
Addr: "湖南省",
Like: "写代码",
},
})
添加用户详情,关联已有用户
这个场景特别适合网站的注册,以及后续信息完善
刚开始注册的时候,只需要填写很基本的信息,这就是添加主表的一条记录
注册进去之后,去个人中心,添加头像,修改地址...
这就是添加附表
DB.Create(&UserInfo{
UserID: 2,
Addr: "南京市",
Like: "吃饭",
})
当然,也可以直接把用户对象传递进来
我们需要改一下表结构
type User struct {
ID uint
Name string
Age int
Gender bool
UserInfo UserInfo // 通过UserInfo可以拿到用户详情信息
}
type UserInfo struct {
User *User // 要改成指针,不然就嵌套引用了
UserID uint // 外键
ID uint
Addr string
Like string
}
不限于重新迁移,直接添加即可
var user User
DB.Take(&user, 2)
DB.Create(&UserInfo{
User: &user,
Addr: "南京市",
Like: "吃饭",
})
查询
一般是通过主表查副表
var user User
DB.Preload("UserInfo").Take(&user)
fmt.Println(user)
8.一对多关系
我们先从一对多开始多表关系的学习
因为一对多的关系生活中到处都是
例如
老板与员工
女神和舔狗
老师和学生
班级与学生
用户与文章
...
一对多关系表结构建立
在gorm中,官方文档是把一对多关系分为了两类,
Belongs To 属于谁
Has Many 我拥有的
他们本来是一起的,本教程把它们合在一起讲
我们以用户和文章为例
一个用户可以发布多篇文章,一篇文章属于一个用户
type User struct {
ID uint `gorm:"size:4"`
Name string `gorm:"size:8"`
Articles []Article // 用户拥有的文章列表
}
type Article struct {
ID uint `gorm:"size:4"`
Title string `gorm:"size:16"`
UserID uint // 属于 这里的类型要和引用的外键类型一致,包括大小
User User // 属于
}
关于外键命名,外键名称就是关联表名+ID,类型是uint
重写外键关联
type User struct {
ID uint `gorm:"size:4"`
Name string `gorm:"size:8"`
Articles []Article `gorm:"foreignKey:UID"` // 用户拥有的文章列表
}
type Article struct {
ID uint `gorm:"size:4"`
Title string `gorm:"size:16"`
UID uint // 属于
User User `gorm:"foreignKey:UID"` // 属于
}
这里有个地方要注意
我改了Article 的外键,将UID作为了外键,那么User这个外键关系就要指向UID
与此同时,User所拥有的Articles也得更改外键,改为UID
重写外键引用
type User struct {
ID uint `gorm:"size:4"`
Name string `gorm:"size:8"`
Articles []Article `gorm:"foreignKey:UserName;references:Name"` // 用户拥有的文章列表
}
type Article struct {
ID uint `gorm:"size:4"`
Title string `gorm:"size:16"`
UserName string
User User `gorm:"references:Name"` // 属于
}
这一块的逻辑比较复杂
一对多的添加
创建用户,并且创建文章
a1 := Article{Title: "python"}
a2 := Article{Title: "golang"}
user := User{Name: "枫枫", Articles: []Article{a1, a2}}
DB.Create(&user)
gorm自动创建了两篇文章,以及创建了一个用户,还将他们的关系给关联上了
创建文章,关联已有用户
a1 := Article{Title: "golang零基础入门", UserID: 1}
DB.Create(&a1)
var user User
DB.Take(&user, 1)
DB.Create(&Article{Title: "python零基础入门", User: user})