教程 > gorm 教程 > 阅读:89

gorm many to many——迹忆客-ag捕鱼王app官网

many to many 会在两个 model 中添加一张连接表。

例如,我们的应用包含了 user 和 language,且一个 user 可以说多种 language,多个 user 也可以说一种 language。

// user 拥有并属于多种 language,`user_languages` 是连接表
type user struct {
  gorm.model
  languages []language `gorm:"many2many:user_languages;"`
}
type language struct {
  gorm.model
  name string
}

当使用 gorm 的 automigrate 为 user 创建表时,gorm 会自动创建连接表


反向引用

声明

// 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;"`
}

检索

// 检索 user 列表并预加载 language
func getallusers(db *gorm.db) ([]user, error) {
    var users []user
    err := db.model(&user{}).preload("languages").find(&users).error
    return users, err
}
// 检索 language 列表并预加载 user
func getalllanguages(db *gorm.db) ([]language, error) {
    var languages []language
    err := db.model(&language{}).preload("users").find(&languages).error
    return languages, err
}

重写外键

对于 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

若要重写它们,可以使用标签 foreignkeyreferencesjoinforeignkeyjoinreferences。当然,我们不需要使用全部的标签,你可以仅使用其中的一个重写部分的外键、引用。

type user struct {
    gorm.model
    profiles []profile `gorm:"many2many:user_profiles;foreignkey:refer;joinforeignkey:userreferid;references:userrefer;joinreferences:profilerefer"`
    refer    uint      `gorm:"index:,unique"`
}
type profile struct {
    gorm.model
    name      string
    userrefer uint `gorm:"index:,unique"`
}
// 会创建连接表:user_profiles
//   foreign key: user_refer_id, reference: users.refer
//   foreign key: profile_refer, reference: profiles.user_refer

注意 : 某些数据库只允许在唯一索引字段上创建外键,如果您在迁移时会创建外键,则需要指定 unique index 标签。


自引用 many2many

自引用 many2many 关系

type user struct {
  gorm.model
    friends []*user `gorm:"many2many:user_friends"`
}
// 会创建连接表:user_friends
//   foreign key: user_id, reference: users.id
//   foreign key: friend_id, reference: users.id

预加载

gorm 可以通过 preload 预加载 has many 关联的记录。


many2many 的 curd

查看 关联模式 获取 many2many 相关的用法


自定义连接表

jointable可以是一个全功能的模型,比如有soft delete,hooks支持等等更多的字段,你可以用setupjointable来设置,例如:

注意 : 自定义连接表要求外键是复合主键或复合唯一索引

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 (personaddress) beforecreate(db *gorm.db) error {
  // ...
}
// 修改 person 的 addresses 字段的连接表为 personaddress
// personaddress 必须定义好所需的外键,否则会报错
err := db.setupjointable(&person{}, "addresses", &personaddress{})

外键约束

你可以通过为标签 constraint 配置 onupdateondelete 实现外键约束,在使用 gorm 进行迁移时它会被创建,例如:

type user struct {
  gorm.model
  languages []language `gorm:"many2many:user_speaks;"`
}
type language struct {
  code string `gorm:"primarykey"`
  name string
}
// create table `user_speaks` (`user_id` integer,`language_code` text,primary key (`user_id`,`language_code`),constraint `fk_user_speaks_user` foreign key (`user_id`) references `users`(`id`) on delete set null on update cascade,constraint `fk_user_speaks_language` foreign key (`language_code`) references `languages`(`code`) on delete set null on update cascade);

你也可以在删除记录时通过 select 来删除 many2many 关系的记录。


复合外键

如果我们的模型使用了 复合主键,gorm 会默认启用复合外键。

我们也可以覆盖默认的外键、指定多个外键,只需用逗号分隔那些键名,例如:

type tag struct {
  id     uint   `gorm:"primarykey"`
  locale string `gorm:"primarykey"`
  value  string
}
type blog struct {
  id         uint   `gorm:"primarykey"`
  locale     string `gorm:"primarykey"`
  subject    string
  body       string
  tags       []tag `gorm:"many2many:blog_tags;"`
  localetags []tag `gorm:"many2many:locale_blog_tags;foreignkey:id,locale;references:id"`
  sharedtags []tag `gorm:"many2many:shared_blog_tags;foreignkey:id;references:id"`
}
// 连接表:blog_tags
//   foreign key: blog_id, reference: blogs.id
//   foreign key: blog_locale, reference: blogs.locale
//   foreign key: tag_id, reference: tags.id
//   foreign key: tag_locale, reference: tags.locale
// 连接表:locale_blog_tags
//   foreign key: blog_id, reference: blogs.id
//   foreign key: blog_locale, reference: blogs.locale
//   foreign key: tag_id, reference: tags.id
// 连接表:shared_blog_tags
//   foreign key: blog_id, reference: blogs.id
//   foreign key: tag_id, reference: tags.id

查看笔记

扫码一下
查看教程更方便
网站地图