Has Many

Has Many

has many 關聯會設定與另一個模型的一對多連線,與 has one 不同,擁有者可以有零個或多個模型實例。

例如,如果您的應用程式包含使用者和信用卡,而每個使用者都可以擁有許多信用卡。

宣告

// User has many CreditCards, UserID is the foreign key
type User struct {
gorm.Model
CreditCards []CreditCard
}

type CreditCard struct {
gorm.Model
Number string
UserID uint
}

擷取

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

覆寫外來金鑰

若要定義 has many 關係,必須存在外來金鑰。預設外來金鑰的名稱是擁有者的類型名稱加上其主鍵欄位的名稱

例如,若要定義屬於 User 的模型,外來金鑰應為 UserID

若要使用另一個欄位作為外來金鑰,您可以使用 foreignKey 標籤自訂它,例如

type User struct {
gorm.Model
CreditCards []CreditCard `gorm:"foreignKey:UserRefer"`
}

type CreditCard struct {
gorm.Model
Number string
UserRefer uint
}

覆寫參照

GORM 通常會使用擁有者的主鍵作為外來金鑰的值,對於上述範例,它是 UserID

當您將信用卡指派給使用者時,GORM 會將使用者的 ID 儲存到信用卡的 UserID 欄位中。

您可以使用標籤 references 變更它,例如

type User struct {
gorm.Model
MemberNumber string
CreditCards []CreditCard `gorm:"foreignKey:UserNumber;references:MemberNumber"`
}

type CreditCard struct {
gorm.Model
Number string
UserNumber string
}

多型關聯

GORM 支援 has onehas many 的多型關聯,它會將擁有的實體的資料表名稱儲存到多型類型欄位中,將主鍵值儲存到多型欄位中

type Dog struct {
ID int
Name string
Toys []Toy `gorm:"polymorphic:Owner;"`
}

type Toy struct {
ID int
Name string
OwnerID int
OwnerType string
}

db.Create(&Dog{Name: "dog1", Toys: []Toy{{Name: "toy1"}, {Name: "toy2"}}})
// INSERT INTO `dogs` (`name`) VALUES ("dog1")
// INSERT INTO `toys` (`name`,`owner_id`,`owner_type`) VALUES ("toy1","1","dogs"), ("toy2","1","dogs")

您可以使用標籤 polymorphicValue 變更多型類型值,例如

type Dog struct {
ID int
Name string
Toys []Toy `gorm:"polymorphic:Owner;polymorphicValue:master"`
}

type Toy struct {
ID int
Name string
OwnerID int
OwnerType string
}

db.Create(&Dog{Name: "dog1", Toys: []Toy{{Name: "toy1"}, {Name: "toy2"}}})
// INSERT INTO `dogs` (`name`) VALUES ("dog1")
// INSERT INTO `toys` (`name`,`owner_id`,`owner_type`) VALUES ("toy1","1","master"), ("toy2","1","master")

使用 Has Many 進行 CRUD

請參閱 關聯模式 以了解如何使用 has many 關聯

Eager Loading

GORM 允許使用 Preload eager loading has many 關聯,有關詳細資訊,請參閱 Preloading (Eager loading)

Self-Referential Has Many

type User struct {
gorm.Model
Name string
ManagerID *uint
Team []User `gorm:"foreignkey:ManagerID"`
}

FOREIGN KEY 約束

您可以使用標籤 constraint 設定 OnUpdateOnDelete 約束,它會在使用 GORM 進行遷移時建立,例如

type User struct {
gorm.Model
CreditCards []CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}

type CreditCard struct {
gorm.Model
Number string
UserID uint
}

您也可以在刪除時使用 Select 刪除選定的 has many 關聯,有關詳細資訊,請參閱 使用 Select 進行刪除

白金贊助商

黃金贊助商

白金贊助商

黃金贊助商