[TOC]
說明
請先閱讀官方文檔,由于官方文檔對每個例子和概念解釋比較簡單,官方文檔中個人認為比較難理解的概念在正文章節(jié)進行解釋
本文須與官方文檔伴食,否則將不知所云。
可對應 學習項目 實踐驗證。
參考
正文
關系
foreignkey & association foreignkey
//情況A:不指定外鍵和關聯(lián)外鍵
type User struct {
gorm.Model
CreditCard CreditCard
}
type CreditCard struct {
gorm.Model
UserID uint
Number string
}
//情況B:外鍵和關聯(lián)外鍵
type User struct {
gorm.Model
Refer string
CreditCard CreditCard `gorm:"ForeignKey:ReferRela;AssociationForeignKey:Refer"`
}
type CreditCard struct {
gorm.Model
ReferRela uint
Number string
}
理解:
- 在情況A下,默認
credit_cards.user_id為ForeignKey,對應users.id為AssociationForeignKey,即某條users表的記錄id=1234,那么credit_cards表中的user_id=1234的記錄屬于與其對應; - 在情況B下,由于顯式指定了外鍵和關聯(lián)外鍵,則
credit_cards.refer_rela對應users.refer;
后文多種關系中都涉及此兩鍵,但是在 Many to Many 關聯(lián)關系中使用方式稍有不同。
foreignkey:B 表關聯(lián) A 表的字段association foreignkey:A 表被 B 表關聯(lián)的字段
即:A 表的association foreignkey對應 B表的foreignkey,兩表兩值相等的記錄具有關聯(lián)關系。
后文多種關系中都涉及此兩個鍵,用法是一樣的。默認不指定的時候 A 表的association foreignkey為其primary key,B 表的foreignkey為 A 表表名+A 表 primary key。
Belongs To & Has One
//Profile Belongs To User
type User struct {
gorm.Model
Name string
}
// `Profile` 屬于 `User`, 外鍵是`UserID`
type Profile struct {
gorm.Model
UserID int
User User
Name string
}
//User Has One Profile
type User struct {
gorm.Model
Name string
Profile Profile
}
// `Profile` 屬于 `User`, 外鍵是`UserID`
type Profile struct {
gorm.Model
UserID int
Name string
}
理解:
兩者區(qū)別在于主體(主語)不同,在邏輯上孿生:
- Belongs To :以 Profile 為主體,Profile屬于 User?!狿rofile 內(nèi)持有 User;
- Has One:以 User 為主體,User 擁有 Profile。——User 內(nèi)持有 Profile。
兩者的ForeignKey和AssociationForeignKey關系是一樣的,都是在 Profile 里定義ForeignKey——Profile.UserID,其對應的是User的PrimerKey(即AssociationForeignKey)——User.ID
根據(jù)以上兩種定義方式在數(shù)據(jù)庫創(chuàng)建表結構沒有差別,但在應用程序內(nèi)對數(shù)據(jù)操作有區(qū)別(設計目的|效果)。就查詢而言,前者可以查詢出攜帶對應 User 信息的 Profile;后者可以查詢出攜帶對應 Profile 信息的 User。
多態(tài)關聯(lián)
除Many To Many中不能使用多態(tài)關聯(lián)
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
}
理解:toys.owner_id對應cats.id和dogs.id,toys.owner_type對應cat和dog。
Has Many & Many To Many
通過切片指定對多關系
`gorm:"many2many:關系表命;"`指定多對多關系
在Many To Many中foreignkey & association foreignkey不做方向區(qū)分,都是指定關系表對應的實體表字段
association_jointable_foreignkey&jointable_foreignkey指定關系表中字段名
關系的使用
通過 gorm.DB.Set(xxx) 或者 Struct Tag 定義關系行為:
- gorm:association_autoupdate——自動更新關聯(lián)開關
- gorm:association_autocreate——自動創(chuàng)建關聯(lián)開關
- gorm: save_associations——前兩者的和
- gorm:association_save_reference——關聯(lián)引用保存開關
// Set set setting by name, which could be used in callbacks, will clone a new db, and update its setting
func (s *DB) Set(name string, value interface{}) *DB {
return s.clone().InstantSet(name, value)
}
根據(jù) Set 方法的注釋說明,返回的是 DB 的副本,則此設置只在一次 DB 構造執(zhí)行中有效。
方法
db.Model(&user).Association("Languages")
指定表、記錄 ID
指定字段
后面跟操作方法如下
- Find(&languages)——查詢匹配的關聯(lián)記錄
- Append(Language{Name: "DE"})——添加關聯(lián)
- Replace([]Language{languageZH, languageEN})——替換關聯(lián)
- Delete([]Language{languageZH, languageEN})——刪除關聯(lián)
- Clear()——清空關聯(lián)
- Count()——返回關聯(lián)記錄數(shù)量
Preloading (預加載)
Preload("Orders")和Find(&users)實際作用與語義剛好相反。
- 從方法語義來說,只管感覺是加載 Orders 表記錄,根據(jù) Orders 記錄查詢所有關聯(lián)的 Users 記錄
- 實際過程是,加載 Users 記錄,更具 Users 記錄查詢關聯(lián)的 Orders 記錄
并且可以在 Preload 內(nèi)指定 Orders 的篩選條件,可以配合 Where 方法指定 Users 的篩選條件。