1. 关联

1.1. 自动创建/更新

GORM 将在创建或保存一条记录的时候自动保存关联和它的引用,如果关联有一个主键, GORM 将调用 Update 来更新它, 不然,它将会被创建。

  1. user := User{
  2. Name: "jinzhu",
  3. BillingAddress: Address{Address1: "Billing Address - Address 1"},
  4. ShippingAddress: Address{Address1: "Shipping Address - Address 1"},
  5. Emails: []Email{
  6. {Email: "jinzhu@example.com"},
  7. {Email: "jinzhu-2@example@example.com"},
  8. },
  9. Languages: []Language{
  10. {Name: "ZH"},
  11. {Name: "EN"},
  12. },
  13. }
  14. db.Create(&user)
  15. //// BEGIN TRANSACTION;
  16. //// INSERT INTO "addresses" (address1) VALUES ("Billing Address - Address 1");
  17. //// INSERT INTO "addresses" (address1) VALUES ("Shipping Address - Address 1");
  18. //// INSERT INTO "users" (name,billing_address_id,shipping_address_id) VALUES ("jinzhu", 1, 2);
  19. //// INSERT INTO "emails" (user_id,email) VALUES (111, "jinzhu@example.com");
  20. //// INSERT INTO "emails" (user_id,email) VALUES (111, "jinzhu-2@example.com");
  21. //// INSERT INTO "languages" ("name") VALUES ('ZH');
  22. //// INSERT INTO user_languages ("user_id","language_id") VALUES (111, 1);
  23. //// INSERT INTO "languages" ("name") VALUES ('EN');
  24. //// INSERT INTO user_languages ("user_id","language_id") VALUES (111, 2);
  25. //// COMMIT;
  26. db.Save(&user)

1.2. 关闭自动更新

如果你的关联记录已经存在在数据库中, 你可能会不想去更新它。

你可以设置 gorm:association_autoupdatefalse

  1. // 不更新有主键的关联,但会更新引用
  2. db.Set("gorm:association_autoupdate", false).Create(&user)
  3. db.Set("gorm:association_autoupdate", false).Save(&user)

或者使用 GORM 的标签, gorm:"association_autoupdate:false"

  1. type User struct {
  2. gorm.Model
  3. Name string
  4. CompanyID uint
  5. // 不更新有主键的关联,但会更新引用
  6. Company Company `gorm:"association_autoupdate:false"`
  7. }

1.3. 关闭自动创建

即使你禁用了 AutoUpdating, 仍然会创建没有主键的关联,并保存它的引用。

你可以通过把 gorm:association_autocreate 设置为 false 来禁用这个行为。

  1. // 不创建没有主键的关联,不保存它的引用。
  2. db.Set("gorm:association_autocreate", false).Create(&user)
  3. db.Set("gorm:association_autocreate", false).Save(&user)

或者使用 GORM 标签, gorm:"association_autocreate:false"

  1. type User struct {
  2. gorm.Model
  3. Name string
  4. // 不创建没有主键的关联,不保存它的引用。
  5. Company1 Company `gorm:"association_autocreate:false"`
  6. }

1.4. 关闭自动创建/更新

禁用 AutoCreateAutoUpdate,你可以一起使用它们两个的设置。

  1. db.Set("gorm:association_autoupdate", false).Set("gorm:association_autocreate", false).Create(&user)
  2. type User struct {
  3. gorm.Model
  4. Name string
  5. Company Company `gorm:"association_autoupdate:false;association_autocreate:false"`
  6. }

或者使用 gorm:save_associations

  1. db.Set("gorm:save_associations", false).Create(&user)
  2. db.Set("gorm:save_associations", false).Save(&user)
  3. type User struct {
  4. gorm.Model
  5. Name string
  6. Company Company `gorm:"association_autoupdate:false"`
  7. }

1.5. 关闭保存引用

如果你不想当更新或保存数据的时候保存关联的引用, 你可以使用下面的技巧

  1. db.Set("gorm:association_save_reference", false).Save(&user)
  2. db.Set("gorm:association_save_reference", false).Create(&user)

或者使用标签

  1. type User struct {
  2. gorm.Model
  3. Name string
  4. CompanyID uint
  5. Company Company `gorm:"association_save_reference:false"`
  6. }

1.6. 关联模式

关联模式包含一些可以轻松处理与关系相关的事情的辅助方法。

  1. // 开启关联模式
  2. var user User
  3. db.Model(&user).Association("Languages")
  4. // `user` 是源表,必须包含主键
  5. // `Languages` 是源表关系字段名称。
  6. // 只有上面两个条件都能匹配,关联模式才会生效, 检查是否正常:
  7. // db.Model(&user).Association("Languages").Error

1.6.1. 查找关联

查找匹配的关联

  1. db.Model(&user).Association("Languages").Find(&languages)

1.6.2. 增加关联

many to manyhas many 新增关联, 为 has one, belongs to 替换当前关联

  1. db.Model(&user).Association("Languages").Append([]Language{languageZH, languageEN})
  2. db.Model(&user).Association("Languages").Append(Language{Name: "DE"})

1.6.3. 替换关联

用一个新的关联替换当前关联

  1. db.Model(&user).Association("Languages").Replace([]Language{languageZH, languageEN})
  2. db.Model(&user).Association("Languages").Replace(Language{Name: "DE"}, languageEN)

1.6.4. 删除关联

删除源和参数对象之间的关系, 只会删除引用,不会删除他们在数据库中的对象。

  1. db.Model(&user).Association("Languages").Delete([]Language{languageZH, languageEN})
  2. db.Model(&user).Association("Languages").Delete(languageZH, languageEN)

1.6.5. 清理关联

删除源和当前关联之间的引用,不会删除他们的关联

  1. db.Model(&user).Association("Languages").Clear()

1.6.6. 统计关联

返回当前关联的统计数

  1. db.Model(&user).Association("Languages").Count()