一对多关系

一对多关系

我们先从一对多开始多表关系的学习

因为一对多的关系生活中到处都是

例如

老板与员工
女神和舔狗
老师和学生
班级与学生
用户与文章
...

一对多关系 表结构建立

在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   `gorm:"size:4"` // 属于   这里的类型要和引用的外键类型一致,包括大小
  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   `gorm:"size:4"` // 属于
  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"` // 属于
}CopyErrorOK!

比如有1个用户

id name
1 枫枫

之前的外键关系是这样表示文章的

id title user_id
1 python 1
2 javascript 1
3 golang 1

如果改成直接关联Name,那就变成了这样

id title user_name
1 python 枫枫
2 javascript 枫枫
3 golang 枫枫

虽然这样很方便,但是非常不适合在实际项目中这样用

我们还是用第一版的表结构做一对多关系的增删改查

一对多的添加

创建用户,并且创建文章

a1 := Article{Title: "python"}
a2 := Article{Title: "golang"}
user := User{Name: "枫枫", Articles: []Article{a1, a2}}
DB.Create(&user)
// 或者
DB.Create(&User{
		Name: "lcx",
		Articles: []Article{
			{Title: "Python"},
			{Title: "Golang"},
		},
	})

gorm自动创建了两篇文章,以及创建了一个用户,还将他们的关系给关联上了

创建文章,关联已有用户

DB.Create(&Article{
    Title:  "Java",
    UserID: 1,
})

// 会创建一个张三的用户并绑定
DB.Create(&Article{
    Title: "PHP",
    User: User{
        Name: "张三",
    },
})

// 给现有的用户绑定文章
var user User
DB.Take(&user, 2)
DB.Create(&Article{
    Title: "C##",
    User:  user,
})

外键添加

给现有用户绑定文章

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, 1)
var article Article
DB.Take(&article, 6)
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)
// {1 lcx []}

直接这样,是显示不出文章列表

预加载

我们必须要使用预加载来加载文章列表

var user User
DB.Preload("Articles").Take(&user, 1)
fmt.Println(user)CopyErrorOK!

预加载的名字就是外键关联的属性名

查询文章,显示文章用户的信息

同样的,使用预加载

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)

本文作者:春游去动物园

本文链接:https://www.cnblogs.com/chunyouqudongwuyuan/p/17984087

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   春游去动物园  阅读(17)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开
  1. 1 生分 川青
生分 - 川青
00:00 / 00:00
An audio error has occurred.

生分 - 川青

词:莎子

曲:邵翼天

编曲:林亦

混音:罗杨轩

吉他:林亦

制作人:谢宇伦

监制:曾炜超/陈显

策划:+7

统筹:黄染染

出品:漫吞吞文化

『酷狗音乐人 • 星曜计划』

全方位推广,见证星力量!

「版权所有未经许可 不得商业翻唱或使用」

我们怎么变得那么生分

用了几年也没解开疑问

有些事你不提我也不问

在陌生与熟悉间找平衡

有些话一开口会伤人

有些话一开口会伤人

所以我选择默不作声

所以我选择默不作声

爱一个人

若甘愿陪衬

甘愿牺牲

也许换个名分

也不是没可能

我不怕在爱里做个蠢人

我不怕在爱里做个蠢人

也不怕爱过之后再分

也不怕爱过之后再分

爱一个人

有万种身份

万种可能

只是没想到

我们最后友人相称

我们怎么变得那么生分

我们怎么变得那么生分

连说话都要掌握好分寸

怕不注意流言

见缝插针

怕不小心我们

成陌生人

我们怎么变得那么生分

用了几年也没解开疑问

有些事你不提我也不问

在陌生与熟悉间找平衡

有些话一开口会伤人

有些话一开口会伤人

所以我选择默不作声

所以我选择默不作声

爱一个人

若甘愿陪衬

甘愿牺牲

也许换个名分

也不是没可能

我不怕在爱里做个蠢人

我不怕在爱里做个蠢人

也不怕爱过之后再分

也不怕爱过之后再分

爱一个人

有万种身份

万种可能

只是没想到我们最后

友人相称

我们怎么变得那么生分

连说话都要掌握好分寸

怕不注意流言见缝插针

怕不小心我们成陌生人

我们怎么变得那么生分

用了几年也没解开疑问

有些事你不提我也不问

在陌生与熟悉间找平衡

我们怎么变得那么生分

我们怎么变得那么生分

连说话都要掌握好分寸

怕不注意流言见缝插针

怕不小心我们成陌生人

我们怎么变得那么生分

用了几年也没解开疑问

有些事你不提我也不问

在陌生与熟悉间找平衡