1、所属
Belongs to ( belongs to
) 関連付けは、宣言されたモデルの各インスタンスが他のモデルのインスタンスに「属する」ように、別のモデルとの 1 対 1 の接続を設定します。
たとえば、アプリケーションにユーザー (ユーザー) と会社 (会社) が含まれており、各ユーザーを 1 つの会社にしか割り当てることができない場合、次のタイプはこの関係を表します。ここで、User
オブジェクトにはCompanyID
と があることに注意してくださいCompany
。デフォルトでは、CompanyID
はテーブル間の外部キー リレーションシップを作成するために暗黙的に使用されるため、内部構造を設定するために構造体User
にCompany
含める必要があります。User
Company
// `User` belongs to `Company`, `CompanyID` is the foreign key
type User struct {
gorm.Model
Name string
CompanyID int
Company Company
}
type Company struct {
ID int
Name string
}
内部の設定の詳細については、 Eager Loadingを参照してください。
1.1 外部キーのオーバーライド
属している関係を定義するには、外部キーが存在する必要があります。デフォルトの外部キーは、所有者 (所有者) のタイプ名とそのプライマリ フィールド名を使用します。
上記の例では、モデルが属するモデルを定義するにはCompany
、User
慣例により、外部キーは次のようになります。CompanyID
GORM は、外部キーをカスタマイズする方法を提供します。次に例を示します。
type User struct {
gorm.Model
Name string
CompanyRefer int
Company Company `gorm:"foreignKey:CompanyRefer"`
// use CompanyRefer as foreign key
}
type Company struct {
ID int
Name string
}
1.2 参照のオーバーライド
所属関係の場合、GORMは通常、所有者の主キー フィールドを外部キーの値として使用しますCompany
。ID
ユーザーを会社に割り当てると、GORM はID
会社をユーザーのフィールドに保存しますCompanyID
。次のように、ラベルごとに変更
できます。references
type User struct {
gorm.Model
Name string
CompanyID string
Company Company `gorm:"references:Code"` // use Code as references
}
type Company struct {
ID int
Code string
Name string
}
GORM は通常、リレーションが であると推測します
has one
。オーバーライド外部キー名が所有者型に既に存在する場合は、belongs to
リレーションで指定する必要がありますreferences
。
type User struct {
gorm.Model
Name string
CompanyID string
Company Company `gorm:"references:CompanyID"` // use Company.CompanyID as references
}
type Company struct {
CompanyID int
Code string
Name string
}
1.3 属している CRUD
使用するbelongs to
関係の関連付けモード(Association Mode )
1.4 イーガーローディング
GORM では、 EagerLoading 属性の関連Preload
付けを使用できます。詳細については、EagerLoading (Just-In-Time Loading) を参照してください。Joins
belongs to
1.5 外部キー制約
タグを使用して制約constraint
を設定すると、移行で作成されます。次に例を示します。OnUpdate
OnDelete
GORM
type User struct {
gorm.Model
Name string
CompanyID int
Company Company `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}
type Company struct {
ID int
Name string
}
2、ある
has one
関連付け。別のモデルと 1 対 1 で接続しますが、セマンティクス (および結果) がわずかに異なります。この関連付けは、あるモデルの各インスタンスが別のモデルのインスタンスを含むか所有していることを示します。
たとえば、アプリケーションにユーザーとクレジット カードが含まれていて、各ユーザーが持つことができるクレジット カードは 1 つだけであるとします。
2.1 ステートメント
// 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
}
2.2 検索
// 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
}
2.3 外部キーのオーバーライド
リレーションシップの場合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
}
2.4 カバーリファレンス
デフォルトでは、所有エンティティは所有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
}
2.5 ポリモルフィック アソシエーション
GORM はとの多態的な関連付けをサポートしhas one
、エンティティのテーブル名を多態型のフィールドに保存し、主キーを多態フィールドに保存します。has 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")
2.6 Has One を使用した CRUD
関連モデルを参照してください。has one
2.7 プリロード
GORM では、アソシエーションPreload
のプリロードが可能です。詳細については、プリロード (オンザフライ ロード)を参照してください。Joins
has one
自己参照には 1 つある
type User struct {
gorm.Model
Name string
ManagerID *uint
Manager *User
}
2.8 外部キー制約
GORMの移行時に作成されるタグを使用して制約をconstraint
設定できます。たとえば、次のようになります。OnUpdate
OnDelete
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
関連付けを削除することもできます
3、たくさんある
3.1 たくさんある
has many
関連付け、別のモデルとの1 対多 ( 1 対多has one
) の接続を確立します。所有モデルとは異なり、所有者は 0 個以上のモデル インスタンスを持つことができます。
たとえば、アプリケーションにユーザーとクレジット カードが含まれており、各ユーザーが多数のクレジット カードを持つことができる場合です。
3.2 宣言する
// 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
}
3.3 検索
// 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
}
3.4 外部キーのオーバーライド
リレーションシップを定義するにはhas many
、外部キーが存在する必要があります。デフォルトの外部キーの名前は、所有者の型名とその主キー フィールドの名前です。
たとえば、User
に属するモデルを定義するには、外部キーは である必要がありますUserID
。
他のフィールドを外部キーとして使用して、ラベルをカスタマイズできますforeignKey
。次に例を示します。
type User struct {
gorm.Model
CreditCards []CreditCard `gorm:"foreignKey:UserRefer"`
}
type CreditCard struct {
gorm.Model
Number string
UserRefer uint
}
3.5 参照のオーバーライド
GORM は通常、所有者の主キーを外部キーの値として使用します。上記の例でUser
はID
、
ユーザーにクレジット カードを割り当てると、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
}
3.6 ポリモーフィック関連
GORM は多態的な関連付けをサポートし、エンティティのテーブル名を多態的な型 (type) のフィールドに保存し、主キーの値を多態的なフィールドに保存します
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")
3.7 Has Many を使用した CRUD
関連モデルを参照してください。has many
3.8 プリロード
GORM では、プリロードを使用してアソシエーションをプリロードできますPreload
。has many
詳細については、プリロード (高速ロード)を参照してください。
自己参照には多くの
type User struct {
gorm.Model
Name string
ManagerID *uint
Team []User `gorm:"foreignkey:ManagerID"`
}
3.9 外部キー制約
タグの有無にかかわらず制約constraint
を設定できます。これは、GORM の移行時に作成されます。次に例を示します。OnUpdate
OnDelete
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
関連付けを削除することもできます
4、多対多
多対多では、2 つのモデル間に結合テーブルが追加されます。
たとえば、アプリケーションにユーザーと言語が含まれている場合、1 人のユーザーが複数の言語を話すことができ、多くのユーザーが指定された言語を話すことができます。
// 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 を使用してテーブルを作成すると、AutoMigrate
GORMは自動的に結合テーブルを作成します。User
4.1 後方参照
宣言する
// 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
}
4.2 外部キーのオーバーライド
多対多の関係の場合、結合テーブルには 2 つのモデルを参照する外部キーがあります。次に例を示します。
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
それらをオーバーライドするにはforeignKey
、タグreferences
、、、、を使用できます。それらを一緒に使用する必要はありません。そのうちの 1 つを使用して、いくつかの外部キー/参照をオーバーライドできます。joinForeignKey
joinReferences
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
4.3 自己参照型 Many2Many
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
4.4 イーガーローディング
GORM では、プリロードを使用してアソシエーションをプリロードできますPreload
。many2many
詳細については、プリロード (高速ロード)を参照してください。
4.5 Many2Many での CRUD
関連モデルを参照してください。has many
4.6 カスタム結合テーブル
JoinTable
Soft Delete
たとえば、soft delete( )、hook( Hooks
) のサポートと、それを設定するSetupJoinTable
ために使用できるなど、完全に機能するモデルにすることができます。
注:
カスタム接続テーブルの外部キーは、複合主キーまたは複合一意インデックスである必要があります
type Person struct {
ID int
Name string
Addresses []Address `gorm:"many2many:person_address;"`
}
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{
})
4.7 外部キー制約
GORMの移行時に作成されるタグを使用して制約constraint
を設定できます。たとえば、次のようになります。OnUpdate
OnDelete
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
関連付けを削除することもできます
4.8 複合外部キー
モデルが複合主キーを使用している場合、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
5. アソシエーション モデル
5.1 自動作成・更新
GORM は、レコードの作成/更新時にUpsert
自動保存関連付けとその参照を使用します。
user := User{
Name: "jinzhu",
BillingAddress: Address{
Address1: "Billing Address - Address 1"},
ShippingAddress: Address{
Address1: "Shipping Address - Address 1"},
Emails: []Email{
{
Email: "[email protected]"},
{
Email: "[email protected]"},
},
Languages: []Language{
{
Name: "ZH"},
{
Name: "EN"},
},
}
db.Create(&user)
// BEGIN TRANSACTION;
// INSERT INTO "addresses" (address1) VALUES ("Billing Address - Address 1"), ("Shipping Address - Address 1") ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "users" (name,billing_address_id,shipping_address_id) VALUES ("jinzhu", 1, 2);
// INSERT INTO "emails" (user_id,email) VALUES (111, "[email protected]"), (111, "[email protected]") ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "languages" ("name") VALUES ('ZH'), ('EN') ON DUPLICATE KEY DO NOTHING;
// INSERT INTO "user_languages" ("user_id","language_id") VALUES (111, 1), (111, 2) ON DUPLICATE KEY DO NOTHING;
// COMMIT;
db.Save(&user)
関連データを更新する場合は、FullSaveAssociations
次のパターンを使用する必要があります。
db.Session(&gorm.Session{
FullSaveAssociations: true}).Updates(&user)
// ...
// INSERT INTO "addresses" (address1) VALUES ("Billing Address - Address 1"), ("Shipping Address - Address 1") ON DUPLICATE KEY SET address1=VALUES(address1);
// INSERT INTO "users" (name,billing_address_id,shipping_address_id) VALUES ("jinzhu", 1, 2);
// INSERT INTO "emails" (user_id,email) VALUES (111, "[email protected]"), (111, "[email protected]") ON DUPLICATE KEY SET email=VALUES(email);
// ...
5.2 自動作成・更新をスキップする
Select
作成/更新時に自動保存をスキップするには、または を使用できますOmit
。次に例を示します。
user := User{
Name: "jinzhu",
BillingAddress: Address{
Address1: "Billing Address - Address 1"},
ShippingAddress: Address{
Address1: "Shipping Address - Address 1"},
Emails: []Email{
{
Email: "[email protected]"},
{
Email: "[email protected]"},
},
Languages: []Language{
{
Name: "ZH"},
{
Name: "EN"},
},
}
db.Select("Name").Create(&user)
// INSERT INTO "users" (name) VALUES ("jinzhu", 1, 2);
db.Omit("BillingAddress").Create(&user)
// Skip create BillingAddress when creating a user
db.Omit(clause.Associations).Create(&user)
// Skip all associations when creating a user
注:関連付け
の場合、 GORM は結合テーブル参照を作成する前に関連付けを挿入します。関連付けの挿入をスキップしたい場合は、次のようにスキップできます。many2many
db.Omit("Languages.*").Create(&user)
以下のコードは、関連付けとその参照の作成をスキップします
db.Omit("Languages").Create(&user)
5.3Select/Omit
関連フィールドの選択/省略 ( )
user := User{
Name: "jinzhu",
BillingAddress: Address{
Address1: "Billing Address - Address 1", Address2: "addr2"},
ShippingAddress: Address{
Address1: "Shipping Address - Address 1", Address2: "addr2"},
}
// Create user and his BillingAddress, ShippingAddress
// When creating the BillingAddress only use its address1, address2 fields and omit others
db.Select("BillingAddress.Address1", "BillingAddress.Address2").Create(&user)
db.Omit("BillingAddress.Address2", "BillingAddress.CreatedAt").Create(&user)
5.4 アソシエーションモード
Association パターンには、リレーションシップを処理するための一般的なヘルパー メソッドが含まれています。
// Start Association Mode
var user User
db.Model(&user).Association("Languages")
// `user` is the source model, it must contains primary key
// `Languages` is a relationship's field name
// If the above two requirements matched, the AssociationMode should be started successfully, or it should return error
db.Model(&user).Association("Languages").Error
5.4.1 関連付けの検索
マッチング協会
db.Model(&user).Association("Languages").Find(&languages)
条件付きルックアップの関連付け
codes := []string{
"zh-CN", "en-US", "ja-JP"}
db.Model(&user).Where("code IN ?", codes).Association("Languages").Find(&languages)
db.Model(&user).Where("code IN ?", codes).Order("code desc").Association("Languages").Find(&languages)
5.4.2 アペンド・アソシエーション
の場合many to many
、has many
新しい関連付けを追加し、 の場合has one
、belongs to
既存の関連付けを置き換えます
db.Model(&user).Association("Languages").Append([]Language{
languageZH, languageEN})
db.Model(&user).Association("Languages").Append(&Language{
Name: "DE"})
db.Model(&user).Association("CreditCard").Append(&CreditCard{
Number: "411111111111"})
5.4.3 関連付けの置換
現在の関連付けを新しいものに置き換えます
db.Model(&user).Association("Languages").Replace([]Language{
languageZH, languageEN})
db.Model(&user).Association("Languages").Replace(Language{
Name: "DE"}, languageEN)
5.4.4 関連付けの削除
ソースとパラメーターの間の関係が存在する場合は削除します。参照のみが削除され、これらのオブジェクトは DB から削除されません。
db.Model(&user).Association("Languages").Delete([]Language{
languageZH, languageEN})
db.Model(&user).Association("Languages").Delete(languageZH, languageEN)
5.4.5 関連付けのクリア
ソースと関連付けの間のすべての参照を削除しますが、これらの関連付けは削除しません
db.Model(&user).Association("Languages").Clear()
5.4.6 カウント関連付け
現在の関連付けの数を返します
db.Model(&user).Association("Languages").Count()
// Count with conditions
codes := []string{
"zh-CN", "en-US", "ja-JP"}
db.Model(&user).Where("code IN ?", codes).Association("Languages").Count()
5.4.7 バッチデータ
アソシエーション モードは、次のようなバルク データをサポートします。
// Find all roles for all users
db.Model(&users).Association("Role").Find(&roles)
// Delete User A from all user's team
db.Model(&users).Association("Team").Delete(&userA)
// Get distinct count of all users' teams
db.Model(&users).Association("Team").Count()
// For `Append`, `Replace` with batch data, the length of the arguments needs to be equal to the data's length or else it will return an error
var users = []User{
user1, user2, user3}
// e.g: we have 3 users, Append userA to user1's team, append userB to user2's team, append userA, userB and userC to user3's team
db.Model(&users).Association("Team").Append(&userA, &userB, &[]User{
userA, userB, userC})
// Reset user1's team to userA,reset user2's team to userB, reset user3's team to userA, userB and userC
db.Model(&users).Association("Team").Replace(&userA, &userB, &[]User{
userA, userB, userC})
5.5 選択による削除
Select
レコードを削除するときは、 [選択した関係の削除]を使用できますhas one/has many/many2many
。例えば:
// delete user's account when deleting user
db.Select("Account").Delete(&user)
// delete user's Orders, CreditCards relations when deleting user
db.Select("Orders", "CreditCards").Delete(&user)
// delete user's has one/many/many2many relations when deleting user
db.Select(clause.Associations).Delete(&user)
// delete each user's account when deleting users
db.Select("Account").Delete(&users)
注:
アソシエーションは、削除されたレコードにゼロ以外の主キーがある場合にのみ削除されます。GORM は、これらの主キーを選択したアソシエーションを削除する基準として使用します。
// DOESN'T WORK
db.Select("Account").Where("name = ?", "jinzhu").Delete(&User{
})
// will delete all user with name `jinzhu`, but those user's account won't be deleted
db.Select("Account").Where("name = ?", "jinzhu").Delete(&User{
ID: 1})
// will delete the user with name = `jinzhu` and id = `1`, and user `1`'s account will be deleted
db.Select("Account").Delete(&User{
ID: 1})
// will delete the user with id = `1`, and user `1`'s account will be deleted
5.6 関連タグ
鬼ごっこ | 説明 |
---|---|
外部キー | 結合テーブルへの外部キーとして使用される現在のモデルの列名を指定します |
参考文献 | 結合テーブルの外部キーにマップされる参照のテーブルの列名を指定します |
多形的な | モデル名などの多態型を指定 |
polymorphicValue | ポリモーフィック値、デフォルトのテーブル名を指定 |
たくさん | 結合テーブル名を指定 |
joinForeignKey | 現在のテーブルにマップする結合テーブルの外部キー列名を指定します |
結合参照 | 参照のテーブルにマップする結合テーブルの外部キー列名を指定します |
制約 | 関係制約、例: OnUpdate、OnDelete |
6、プリロード(イーガーロード)
6.1 プリロード
GORM をPreload
使用すると、高速読み込みの関連付けを他の SQL で使用できます。次に例を示します。
type User struct {
gorm.Model
Username string
Orders []Order
}
type Order struct {
gorm.Model
UserID uint
Price float64
}
// Preload Orders when find users
db.Preload("Orders").Find(&users)
// SELECT * FROM users;
// SELECT * FROM orders WHERE user_id IN (1,2,3,4);
db.Preload("Orders").Preload("Profile").Preload("Role").Find(&users)
// SELECT * FROM users;
// SELECT * FROM orders WHERE user_id IN (1,2,3,4); // has many
// SELECT * FROM profiles WHERE user_id IN (1,2,3,4); // has one
// SELECT * FROM roles WHERE id IN (4,5,6); // belongs to
6.2 ジョインのプリロード
Preload
単一のクエリで関連データを読み込むと、Join Preload
内部結合を使用して関連データが読み込まれます。次に例を示します。
db.Joins("Company").Joins("Manager").Joins("Account").First(&user, 1)
db.Joins("Company").Joins("Manager").Joins("Account").First(&user, "users.name = ?", "jinzhu")
db.Joins("Company").Joins("Manager").Joins("Account").Find(&users, "users.id IN ?", []int{
1,2,3,4,5})
条件付きで参加
db.Joins("Company", DB.Where(&Company{
Alive: true})).Find(&users)
// SELECT `users`.`id`,`users`.`name`,`users`.`age`,`Company`.`id` AS `Company__id`,`Company`.`name` AS `Company__name` FROM `users` LEFT JOIN `companies` AS `Company` ON `users`.`company_id` = `Company`.`id` AND `Company`.`alive` = true;
Join Preload
1 対 1 の関係で動作します。例:has one
、belong to
6.3 すべてプリロード
作成/更新の場合、同様の で使用できclause.Associations
ます。たとえば、次のようにすべての関連付けに使用できます。Preload
Select
Preload
type User struct {
gorm.Model
Name string
CompanyID uint
Company Company
Role Role
Orders []Order
}
db.Preload(clause.Associations).Find(&users)
clause.Associations
ネストされたアソシエーションをプリロードしませんが、ネストされたプリロードと一緒に使用できます。次に例を示します。
db.Preload("Orders.OrderItems.Product").Preload(clause.Associations).Find(&users)
6.4 条件付きプリロード
GORM では、関連付けの条件付きプリロードが可能で、インライン条件付きのように機能します
// Preload Orders with conditions
db.Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)
// SELECT * FROM users;
// SELECT * FROM orders WHERE user_id IN (1,2,3,4) AND state NOT IN ('cancelled');
db.Where("state = ?", "active").Preload("Orders", "state NOT IN (?)", "cancelled").Find(&users)
// SELECT * FROM users WHERE state = 'active';
// SELECT * FROM orders WHERE user_id IN (1,2) AND state NOT IN ('cancelled');
6.5 カスタムのプリロード SQL
を渡すことで、プリロード SQL をカスタマイズできますfunc(db *gorm.DB) *gorm.DB
。次に例を示します。
db.Preload("Orders", func(db *gorm.DB) *gorm.DB {
return db.Order("orders.amount DESC")
}).Find(&users)
// SELECT * FROM users;
// SELECT * FROM orders WHERE user_id IN (1,2,3,4) order by orders.amount DESC;
6.6 ネストされたプリロード
GORM はネストされたプリロードをサポートします。次に例を示します。
db.Preload("Orders.OrderItems.Product").Preload("CreditCard").Find(&users)
// Customize Preload conditions for `Orders`
// And GORM won't preload unmatched order's OrderItems then
db.Preload("Orders", "state = ?", "paid").Preload("Orders.OrderItems").Find(&users)