多對多

多對多

多對多會在兩個模型之間新增一個關聯表格。

例如,如果您的應用程式包含使用者和語言,而且一個使用者可以說多種語言,且許多使用者可以說一種指定的語言。

// User has and belongs to many languages, `user_languages` is the join table
type User struct {
gorm.Model
Languages []Language `gorm:"many2many:user_languages;"`
}

type Language struct {
gorm.Model
Name string
}

使用 GORM AutoMigrateUser 建立表格時,GORM 會自動建立關聯表格

反向參考

宣告

// User has and belongs to many languages, use `user_languages` as join table
type User struct {
gorm.Model
Languages []*Language `gorm:"many2many:user_languages;"`
}

type Language struct {
gorm.Model
Name string
Users []*User `gorm:"many2many:user_languages;"`
}

擷取

// Retrieve user list with eager loading languages
func GetAllUsers(db *gorm.DB) ([]User, error) {
var users []User
err := db.Model(&User{}).Preload("Languages").Find(&users).Error
return users, err
}

// Retrieve language list with eager loading users
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
}

// Join Table: 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"`
}

// Which creates join table: user_profiles
// foreign key: user_refer_id, reference: users.refer
// foreign key: profile_refer, reference: profiles.user_refer

注意
有些資料庫只允許建立參考具有唯一索引欄位的資料庫外來鍵,因此如果您在移轉時建立資料庫外來鍵,則需要指定 unique index 標籤

自參考多對多

自參考多對多關係

type User struct {
gorm.Model
Friends []*User `gorm:"many2many:user_friends"`
}

// Which creates join table: user_friends
// foreign key: user_id, reference: users.id
// foreign key: friend_id, reference: users.id

熱切載入

GORM 允許熱切載入與 Preload 有許多關聯,請參閱 預載入 (熱切載入) 以取得詳細資訊

使用 Many2Many 進行 CRUD

請查看 關聯模式 以了解如何使用 many2many 關聯

自訂 JoinTable

JoinTable 可以是一個功能齊全的模型,例如具有 Soft DeleteHooks 支援和更多欄位,您可以使用 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 {
// ...
}

// Change model Person's field Addresses' join table to PersonAddress
// PersonAddress must defined all required foreign keys or it will raise error
err := db.SetupJoinTable(&Person{}, "Addresses", &PersonAddress{})

FOREIGN KEY 約束

您可以使用標籤 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 關聯,請查看 使用 Select 刪除 以取得詳細資訊

複合外來鍵

如果您對模型使用 複合主鍵,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"`
}

// Join Table: 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

// Join Table: locale_blog_tags
// foreign key: blog_id, reference: blogs.id
// foreign key: blog_locale, reference: blogs.locale
// foreign key: tag_id, reference: tags.id

// Join Table: shared_blog_tags
// foreign key: blog_id, reference: blogs.id
// foreign key: tag_id, reference: tags.id

另請查看 複合主鍵

白金贊助商

黃金贊助商

白金贊助商

黃金贊助商