GORM-V1-關聯(lián)

[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_idForeignKey,對應users.idAssociationForeignKey,即某條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。

兩者的ForeignKeyAssociationForeignKey關系是一樣的,都是在 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.iddogs.idtoys.owner_type對應catdog。

Has Many & Many To Many

  • 通過切片指定對多關系

  • `gorm:"many2many:關系表命;"`指定多對多關系

  • Many To Manyforeignkey & 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 的篩選條件。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容