Has One

Has One

has one は、別のモデルと一対一となる関連を設定します。関連するモデルによって、セマンティクス(と因果関係)は多少異なります。 このアソシエーションは、モデルの各インスタンスが別のモデルの1つのインスタンスを含んでいるか、または所有していることを示します。

例えば、ユーザーとクレジットカードのモデルがあり、各ユーザーはクレジットカードを1枚しか持つことができないとします。

Declare

// Userは1つだけCreditCardを持ちます。CreditCardIDは外部キーです。
type User struct {
gorm.Model
CreditCard CreditCard
}

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

Retrieve

// Retrieve user list with edger 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を持つモデルの型名にprimary keyを足したものとして作成されます。上記の例では UserIDです。

ユーザーにクレジットカードを渡すと、ユーザーの IDUserID フィールドに保存されます。

別のフィールドを使用したい場合は、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
}

Polymorphism Association

GORMは has onehas many アソシエーションにおいて、polymorphism associationをサポートしています。所有する側のエンティティのテーブル名が polymorphic type のフィールドに保存され、主キーが polymorphic 用のフィールドに保存されます。

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タグを使用して、polymorphic typeとして登録される値を変更できます。例:

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 リレーションを使った処理の詳細については Association Mode を参照してください。

Eager Loading

GORMでは、 Preload または Joins を使うことで、has one リレーションの Eager Loadingを行うことができます。詳細については Preload (Eager loading) を参照してください。

Has One での自己参照

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

外部キー制約

constraint タグを使用することで、 OnUpdate, OnDelete の制約を掛けることができます。指定した制約は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 を参照してください。

Gold Sponsors

Become a Sponsor!

Gold Sponsors

Become a Sponsor!