Has One

Has One

has one 關聯設定與另一個模型的一對一連線,但語意(和後果)略有不同。此關聯表示模型的每個實例都包含或擁有另一個模型的一個實例。

例如,如果您的應用程式包含使用者和信用卡,且每個使用者只能擁有一張信用卡。

宣告

// User has one CreditCard, UserID is the foreign key
type User struct {
gorm.Model
CreditCard CreditCard
}

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

擷取

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

覆寫外來鍵

對於 has one 關係,外來鍵欄位也必須存在,擁有者會將其所屬模型的主鍵儲存到此欄位中。

欄位名稱通常會使用 has one 模型的類型加上其 主鍵 來產生,對於上述範例,欄位名稱為 UserID

當您將信用卡提供給使用者時,它會將使用者的 ID 儲存到其 UserID 欄位中。

如果您想使用另一個欄位來儲存關係,您可以使用標籤 foreignKey 來變更,例如

type User struct {
gorm.Model
CreditCard CreditCard `gorm:"foreignKey:UserName"`
// use UserName as foreign key
}

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

覆寫參照

預設情況下,擁有的實體會將 has one 模型的主鍵儲存到外來鍵中,您可以變更為儲存另一個欄位的值,例如對下列範例使用 Name

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

type User struct {
gorm.Model
Name string `gorm:"index"`
CreditCard CreditCard `gorm:"foreignKey:UserName;references:name"`
}

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

多型關聯

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

type Cat struct {
ID int
Name string
Toy Toy `gorm:"polymorphic:Owner;"`
}

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

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

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

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

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

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

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

使用 Has One 進行 CRUD

請查看 關聯模式 以了解如何使用 has one 關係

Eager Loading

GORM 允許 Eager loading has one 關聯使用 PreloadJoins,詳情請參閱 Preloading (Eager loading)

Self-Referential Has One

type User struct {
gorm.Model
Name string
ManagerID *uint
Manager *User
}

FOREIGN KEY Constraints

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

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

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

刪除時,您也可以使用 Select 刪除選定的 has one 關聯,詳情請查看 Delete with Select

白金贊助商

黃金贊助商

白金贊助商

黃金贊助商