Gorm Many To Many

写cmdb的时候要去做一些软件资源的落库,发布要使用到的应用属性。应用有哪些属性?

应用有它的type类型,是api还是admin,还是job或者task。它的语言是go java.....,它的own也就是属于哪个开发的,这是它的属性。

应用和own是多对多的关系,一个应用表,一个开发表。一个应用有多个负责人,一个开发好几个人迭代这个应用。反过来就是一个开发对应多个应用。

所以应用服务和开发它就是多对多的关系。一个开发对应多个应用,一个应用对应多个开发。

Many To Many

双向一对多就是多对多

如果将学生和课程放在一张表里面即造成了学生数据的冗余,同时又造成了课程数据的冗余。

一对多一般是拆成两张表,但是多对多至少要拆成三张表了。

首先拆分为两张基础表,一张是学生信息表,一张是课程信息表。一种是维护学生的各种信息的,一种是维护课程的各种信息。

这就两张表了,同时还需要一张中间表,中间表就是维护课程和学生关联关系的。

比如一个张三报名了两门课程go和vue,张三的userid是1,在中间表两个userid为1对应的是两个lesson。最后在去做关联操作和关联查询的时候就可以通过这三张表将整个信息查询出来。

其实真正数据冗余的就是中间表,但是中间表也不算冗余,因为只有两个字段,两个字段都是带索引的,不会去占用很多空间。

  • Many to Many 会在两个 model 中添加一张连接表。
  • 例如,您的应用包含了 user language,且一个 user 可以说多种 language,多个 user 也可以说一种 language
  • 当使用 GORM AutoMigrate User 创建表时,GORM 会自动创建连接表(当去建立了多对多的关系,这张中间表gorm就会自动帮你创建)
package main

import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type User struct {
	gorm.Model
	Languages []Language `gorm:"many2many:user_languages;"`
}

type Language struct {
	gorm.Model
	Name string
}

func main() {
	dsn := "root:7PXjAkY!&nlR@tcp(192.168.11.128:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	db.AutoMigrate(Language{}, User{})
}

 2. 反向引用

上面两个的相同点,基于这两个结构体生成数据库表里面的字段,结构都是一模一样的。
Languages []Language `gorm:"many2many:user_languages;"`

这里有两个功能,一个作用是声明多对多关系,它去找哪个类型去和它做多对多关联。

还有一个作用是通过users点出language,其实也就是可以拿到成员的信息,但是其实数据库表是没有这个东西的。(这个就是看场景需不需要通过language点出user)

上面如果做了关联关系,那么至少有一个地方得写这个玩意。

// User 拥有并属于多种 language,`user_languages` 是连接表
type User struct {
    gorm.Model
    Languages []*Language `gorm:"many2many:user_languages;"`
}


type Language struct {
    gorm.Model
    Name string
    Users []*User `gorm:"many2many:user_languages;"`
}
3. 重写外键
对于 many2many 关系,连接表会同时拥有两个模型的外键
type User struct {
    gorm.Model
    Languages []Language `gorm:"many2many:user_languages;"`
}

type Language struct {
    gorm.Model
    Name string
}

// 连接表:user_languages
// foreign key: user_id, reference: users.id
// foreign key: language_id, reference: languages.id
若要重写它们,可以使用标签 foreignKey references joinforeignKey
joinReferences 。(一般正常使用表名.id就足够了,自己写的话容易搞错)
当然,您不需要使用全部的标签,你可以仅使用其中的一个重写部分的外键、引用

在定义多对多关系其实是可以去定义第三张表的,

type Person struct {
ID int
Name string
Addresses []Address `gorm:"many2many:person_addresses;"`
}
type Address struct {
ID uint
Name string
}
type PersonAddress struct {
PersonID int `gorm:"primaryKey"`
AddressID int `gorm:"primaryKey"`
CreatedAt time.Time
DeletedAt gorm.DeletedAt
}
func main() {
// 0、连接数据库
dsn := "root:1@tcp(127.0.0.1:3306)/test_db?
charset=utf8mb4&parseTime=True&loc=Local"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
// 1、自动创建多对多表结构
db.AutoMigrate(
Person{},
Address{},
)
// 2、添加数据
persons := Person{
ID: 1,
Name: "zhangsan",
Addresses: []Address{
{ID: 1, Name: "bj"},
{ID: 2, Name: "sh"},
},
}
db.Create(&persons)
}

猜你喜欢

转载自blog.csdn.net/qq_34556414/article/details/131321449