首页 > 其他分享 >一对多关系

一对多关系

时间:2024-01-24 10:47:17浏览次数:30  
标签:关系 DB user article Article 一对 gorm User

一对多关系

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

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

例如

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

一对多关系 表结构建立

在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)

标签:关系,DB,user,article,Article,一对,gorm,User
From: https://www.cnblogs.com/chunyouqudongwuyuan/p/17984087

相关文章

  • 一对一关系
    一对一关系一对一关系比较少,一般用于表的扩展例如一张用户表,有很多字段那么就可以把它拆分为两张表,常用的字段放主表,不常用的字段放详情表表结构搭建typeUserstruct{IDuintNamestringAgeintGenderboolUserInfoUserInfo//通过UserI......
  • thinkphp 关联模型 一对多关联 主副表查询
    一对多关联查询namespaceapp\model;usethink\Model;classUsersextendsModel{//模型中定义一对多关系的方法用于建立当前模型与另一个模型之间的关系,例如:当前数据表对应的外键表//profile自定义方法名Profile::class关联数据表的模型文件类名......
  • DStream与RDD关系
    RDD是怎么生成的?RDD依靠什么生成?根据DStream来的RDD生成的依据是什么?SparkStreaming中RDD的执行是否和SparkCore中的RDD执行有所不同?运行之后我们对RDD怎么处理?ForEachDStream不一定会触发Job的执行,但是它一定会触发job的产生,和Job是否执行没有关系;问:RDD依靠什么生成的? ......
  • SQL构建表层次关系,递归累加数据
     构建表的上下级关系      有一个需求,表中数据没有关系,如同一个类型的,有多个出库时间。代码--构建表的上下级关系--可以对同一个产品的,有层次关系--使用ROW_NUMBER(),来构建,最上上一级为0INSERTINTOStock([no]--编号,[quantity]......
  • 一篇简短的文章把C++左右值关系讲的透透彻彻
     目录前言C++左值和右值二、右值引用二、右值引用 前言对于C++的左值和右值相信很多人都没有一个很透彻的了解,之前我也是不懂的时候查阅了好多文章,但是讲完我还是一头雾水,直到我遇到一篇宝藏文章,讲的左值右值的关系以及Move函数的用法是相当的清楚,文章链接......
  • mybatis一对多,多对一经典案例及优缺点分析
    准备数据新建俩张表(student表,clalss表)sql语句如下:createtablestudent(sIdintprimarykeyauto_increment,sNamevarchar(20)notnull,cIdintnotnull,constraintf_sid_cidforeignkey(cId)referencesclass(cId))engine=innodb,charset=utf8;createtableclass......
  • Linux系统文件属性按列划分以及各个字段的关系及作用
    按列划分s-li#-i显示inode号码33575030-rw-r--r--1rootroot881Mar609:151.log1.第一列:33575030inode号码2.第二列:-文件类型3.第三列:rw-r--r--九位文件权限rwx4.第四列:1文件的硬链接个数5.第五列:root文件......
  • dotnet 多数据库 sqlite efcore model和entity区别 一对多 多对一 多对多
    efcore-multi-db/MultiDb.slnMicrosoftVisualStudioSolutionFile,FormatVersion12.00#VisualStudio15VisualStudioVersion=15.0.27130.2024MinimumVisualStudioVersion=10.0.40219.1Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}")="......
  • 鸿蒙原生应用/元服务实战-AGC中几个菜单栏的关系
    大家是否清楚AGC这几个菜单栏的相互关系?我的元服务:点击后跳转到“我的应用”列表中的“HarmonyOS”页签,并且过滤出元服务。开发者可以在此模块中管理和运营元服务,例如创建元服务、发布元服务等。我的应用:开发者可以在此模块中管理和运营应用,例如创建应用、配置应用信息、发布应用、......
  • 进程线程关系
    1、什么是进程什么是进程呢?进程是程序的一次启动执行。什么是程序呢?程序是存放在硬盘中的可执行文件,主要包括代码指令和数据。一个进程是一个程序的一次启动和执行,是操作系统将程序装入内存,给程序分配必要的系统资源,并且开始运行程序的指令。进程与程序是什么关系呢?同一......