Many To Many

未匹配的标注
本文档最新版为 v2,旧版本可能放弃维护,推荐阅读最新版!

多对多

多对多为两个模型增加了一个中间表。

例如,如果你的应用包含用户和语言, 一个用户会说多种语言,并且很多用户会说一种特定的语言。

// 用户拥有并属于多种语言, 使用  `user_languages` 作为中间表
type User struct {
    gorm.Model
    Languages         []Language `gorm:"many2many:user_languages;"`
}

type Language struct {
    gorm.Model
    Name string
}

反向关联

// 用户拥有并且属于多种语言,使用 `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;"`
}

db.Model(&language).Related(&users)
//// SELECT * FROM "users" INNER JOIN "user_languages" ON "user_languages"."user_id" = "users"."id" WHERE  ("user_languages"."language_id" IN ('111'))

外键

type CustomizePerson struct {
  IdPerson string             `gorm:"primary_key:true"`
  Accounts []CustomizeAccount `gorm:"many2many:PersonAccount;association_foreignkey:idAccount;foreignkey:idPerson"`
}

type CustomizeAccount struct {
  IdAccount string `gorm:"primary_key:true"`
  Name      string
}

外键会为两个结构体创建一个多对多的关系,并且这个关系将通过外键customize_person_id_personcustomize_account_id_account 保存到中间表 PersonAccount

中间表外键

如果你想改变中间表的外键,你可以用标签 association_jointable_foreignkey, jointable_foreignkey

type CustomizePerson struct {
  IdPerson string             `gorm:"primary_key:true"`
  Accounts []CustomizeAccount `gorm:"many2many:PersonAccount;foreignkey:idPerson;association_foreignkey:idAccount;association_jointable_foreignkey:account_id;jointable_foreignkey:person_id;"`
}

type CustomizeAccount struct {
  IdAccount string `gorm:"primary_key:true"`
  Name      string
}

自引用

为了定义一个自引用的多对多关系,你不得不改变中间表的关联外键。

和来源表外键不同的是它是通过结构体的名字和主键生成的,例如:

type User struct {
  gorm.Model
  Friends []*User `gorm:"many2many:friendships;association_jointable_foreignkey:friend_id"`
}

GORM 将创建一个带外键 user_idfriend_id 的中间表, 并且使用它去保存用户表的自引用关系。

然后你可以像普通关系一样操作它, 例如:

DB.Preload("Friends").First(&user, "id = ?", 1)

DB.Model(&user).Association("Friends").Append(&User{Name: "friend1"}, &User{Name: "friend2"})

DB.Model(&user).Association("Friends").Delete(&User{Name: "friend2"})

DB.Model(&user).Association("Friends").Replace(&User{Name: "new friend"})

DB.Model(&user).Association("Friends").Clear()

DB.Model(&user).Association("Friends").Count()

使用多对

db.Model(&user).Related(&languages, "Languages")
//// SELECT * FROM "languages" INNER JOIN "user_languages" ON "user_languages"."language_id" = "languages"."id" WHERE "user_languages"."user_id" = 111

//  当查询用户时预加载 Language
db.Preload("Languages").First(&user)

更多高级用法, 请参考 Association Mode

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/gorm/v1/many_to...

译文地址:https://learnku.com/docs/gorm/v1/many_to...

上一篇 下一篇
贡献者:1
讨论数量: 1
发起讨论 只看当前版本


KingOfTheWorld
一对多,多对多可以同时存在两张表中吗?
0 个点赞 | 2 个回复 | 问答 | 课程版本 2018