[ go 与 golang | 青训营笔记]
这是我参与「第五届青训营 」伴学笔记创作活动的第 17 天, 在学习了go的相关基础知识以后,可以说是初步的了解了go,接下来,我们将步入全新的环节,今天我们学习go的一个常用orm框架gorm
9.一对多
外键添加
给现有用户绑定文章
var user User
DB.Take(&user, 2)
var article Article
DB.Take(&article, 5)
user.Articles = []Article{article}
DB.Save(&user)
也可以用Append方法
var user User
DB.Take(&user, 2)
var article Article
DB.Take(&article, 5)
//user.Articles = []Article{article}
//DB.Save(&user)
DB.Model(&user).Association("Articles").Append(&article)
给现有文章关联用户
var article Article
DB.Take(&article, 5)
article.UserID = 2
DB.Save(&article)
也可用Append方法
var user User
DB.Take(&user, 2)
var article Article
DB.Take(&article, 5)
DB.Model(&article).Association("User").Append(&user)
查询
查询用户,显示用户的文章列表
var user User
DB.Take(&user, 1)
fmt.Println(user)
直接这样,是显示不出文章列表
预加载
我们必须要使用预加载来加载文章列表
var user User
DB.Preload("Articles").Take(&user, 1)
fmt.Println(user)
预加载的名字就是外键关联的属性名
查询文章,显示文章用户的信息
同样的,使用预加载
var article Article
DB.Preload("User").Take(&article, 1)
fmt.Println(article)
嵌套预加载
查询文章,显示用户,并且显示用户关联的所有文章,这就得用到嵌套预加载了
var article Article
DB.Preload("User.Articles").Take(&article, 1)
fmt.Println(article)
带条件的预加载
查询用户下的所有文章列表,过滤某些文章
var user User
DB.Preload("Articles", "id = ?", 1).Take(&user, 1)
fmt.Println(user)
这样,就只有id为1的文章被预加载出来了
自定义预加载
var user User
DB.Preload("Articles", func(db *gorm.DB) *gorm.DB {
return db.Where("id in ?", []int{1, 2})
}).Take(&user, 1)
fmt.Println(user)
删除
级联删除
删除用户,与用户关联的文章也会删除
var user User
DB.Take(&user, 1)
DB.Select("Articles").Delete(&user)
清除外键关系
删除用户,与将与用户关联的文章,外键设置为null
var user User
DB.Preload("Articles").Take(&user, 2)
DB.Model(&user).Association("Articles").Delete(&user.Articles)
10. 多对多
多对多关系,需要用第三张表存储两张表的关系
表结构搭建
type Tag struct {
ID uint
Name string
Articles []Article `gorm:"many2many:article_tags;"` // 用于反向引用
}
type Article struct {
ID uint
Title string
Tags []Tag `gorm:"many2many:article_tags;"`
}
多对多添加
添加文章,并创建标签
DB.Create(&Article{
Title: "python基础课程",
Tags: []Tag{
{Name: "python"},
{Name: "基础课程"},
},
})
添加文章,选择标签
var tags []Tag
DB.Find(&tags, "name = ?", "基础课程")
DB.Create(&Article{
Title: "golang基础",
Tags: tags,
})
多对多查询
查询文章,显示文章的标签列表
var article Article
DB.Preload("Tags").Take(&article, 1)
fmt.Println(article)
查询标签,显示文章列表
var tag Tag
DB.Preload("Articles").Take(&tag, 2)
fmt.Println(tag)
多对多更新
移除文章的标签
var article Article
DB.Preload("Tags").Take(&article, 1)
DB.Model(&article).Association("Tags").Delete(article.Tags)
fmt.Println(article)
更新文章的标签
var article Article
var tags []Tag
DB.Find(&tags, []int{2, 6, 7})
DB.Preload("Tags").Take(&article, 2)
DB.Model(&article).Association("Tags").Replace(tags)
fmt.Println(article)
自定义连接表
默认的连接表,只有双方的主键id,展示不了更多信息了
这是官方的例子,我修改了一下
type Article struct {
ID uint
Title string
Tags []Tag `gorm:"many2many:article_tags"`
}
type Tag struct {
ID uint
Name string
}
type ArticleTag struct {
ArticleID uint `gorm:"primaryKey"`
TagID uint `gorm:"primaryKey"`
CreatedAt time.Time
}
生成表结构
// 设置Article的Tags表为ArticleTag
DB.SetupJoinTable(&Article{}, "Tags", &ArticleTag{})
// 如果tag要反向应用Article,那么也得加上
// DB.SetupJoinTable(&Tag{}, "Articles", &ArticleTag{})
err := DB.AutoMigrate(&Article{}, &Tag{}, &ArticleTag{})
fmt.Println(err)
操作案例
举一些简单的例子
- 添加文章并添加标签,并自动关联
- 添加文章,关联已有标签
- 给已有文章关联标签
- 替换已有文章的标签
- 添加文章并添加标签,并自动关联
DB.SetupJoinTable(&Article{}, "Tags", &ArticleTag{}) // 要设置这个,才能走到我们自定义的连接表
DB.Create(&Article{
Title: "flask零基础入门",
Tags: []Tag{
{Name: "python"},
{Name: "后端"},
{Name: "web"},
},
})
// CreatedAt time.Time 由于我们设置的是CreatedAt,gorm会自动填充当前时间,
// 如果是其他的字段,需要使用到ArticleTag 的添加钩子 BeforeCreate
- 添加文章,关联已有标签
DB.SetupJoinTable(&Article{}, "Tags", &ArticleTag{})
var tags []Tag
DB.Find(&tags, "name in ?", []string{"python", "web"})
DB.Create(&Article{
Title: "flask请求对象",
Tags: tags,
})
- 给已有文章关联标签
DB.SetupJoinTable(&Article{}, "Tags", &ArticleTag{})
article := Article{
Title: "django基础",
}
DB.Create(&article)
var at Article
var tags []Tag
DB.Find(&tags, "name in ?", []string{"python", "web"})
DB.Take(&at, article.ID).Association("Tags").Append(tags)
- 替换已有文章的标签
var article Article
var tags []Tag
DB.Find(&tags, "name in ?", []string{"后端"})
DB.Take(&article, "title = ?", "django基础")
DB.Model(&article).Association("Tags").Replace(tags)
- 查询文章列表,显示标签
var articles []Article
DB.Preload("Tags").Find(&articles)
fmt.Println(articles)
conda config --add channels mirrors.tuna.tsinghua.edu.cn/anaconda/pk… conda config --set show_channel_urls yes pip install -i pypi.tuna.tsinghua.edu.cn/simple/ mirrors.tuna.tsinghua.edu.cn/tensorflow/…