# Has One
## Has One
`has one` 與另一個模型建立一對一的關聯,但它和一對一關系有些許不同。 這種關聯表明一個模型的每個實例都包含或擁有另一個模型的一個實例。
例如,您的應用包含 user 和 credit card 模型,且每個 user 只能有一張 credit card。
```go
// User 有一張 CreditCard,CreditCardID 是外鍵
type User struct {
gorm.Model
CreditCard CreditCard
}
type CreditCard struct {
gorm.Model
Number string
UserID uint
}
```
## 重寫外鍵
對于 `has one` 關系,同樣必須存在外鍵字段。擁有者將把屬于它的模型的主鍵保存到這個字段。
這個字段的名稱通常由 `has one` 模型的類型加上其 `主鍵` 生成,對于上面的例子,它是 `UserID`。
為 user 添加 credit card 時,它會將 user 的 `ID` 保存到自己的 `UserID` 字段。
如果你想要使用另一個字段來保存該關系,你同樣可以使用標簽 `foreignKey` 來更改它,例如:
```go
type User struct {
gorm.Model
CreditCard CreditCard `gorm:"foreignKey:UserName"`
// 使用 UserName 作為外鍵
}
type CreditCard struct {
gorm.Model
Number string
UserName string
}
```
## 重寫引用
默認情況下,擁有者實體會將 `has one` 對應模型的主鍵保存為外鍵,您也可以修改它,用另一個字段來保存,例如下個這個使用 `Name` 來保存的例子。
您可以使用標簽 `references` 來更改它,例如:
```go
type User struct {
gorm.Model
Name string `sql:"index"`
CreditCard CreditCard `gorm:"foreignkey:UserName;references:name"`
}
type CreditCard struct {
gorm.Model
Number string
UserName string
}
```
## 多態關聯
GORM 為 `has one` 和 `has many` 提供了多態關聯支持,它會將擁有者實體的表名、主鍵都保存到多態類型的字段中。
```go
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` 來更改多態類型的值,例如:
```go
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 的 CURD
查看 [關聯模式](./associations.md#Association-Mode) 獲取 `has one` 相關的用法
## 預加載
GORM 可以通過 `Preload`、`Joins` 預加載 `has one` 關聯的記錄,查看 [預加載](./preload.md) 獲取詳情
## 自引用 Has One
```go
type User struct {
gorm.Model
Name string
ManagerID *uint
Manager *User
}
```
## 外鍵約束
你可以通過標簽 `constraint` 并帶上 `OnUpdate`、`OnDelete` 實現外鍵約束,例如:
```go
type User struct {
gorm.Model
CreditCard CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}
type CreditCard struct {
gorm.Model
Number string
UserID uint
}
```