关联

关联

qianmoQqianmoQ· 更新于 2026-09-23· 阅读 18 分钟· 0 次阅读

登录后可跨设备保存划线和私人笔记登录

自动创建/更新

GORM 在创建或更新记录时,会自动保存关联关系及其引用,使用一种 upsert 技术,主要更新已有关联的外键引用。

创建时自动保存关联

当您创建新记录时,GORM 会自动保存其关联数据,包括向关联表插入数据和管理外键引用。

user := User{
  Name:            "jinzhu",
  BillingAddress:  Address{Address1: "Billing Address - Address 1"},
  ShippingAddress: Address{Address1: "Shipping Address - Address 1"},
  Emails:          []Email{
    {Email: "jinzhu@example.com"},
    {Email: "jinzhu-2@example.com"},
  },
  Languages:       []Language{
    {Name: "ZH"},
    {Name: "EN"},
  },
}


db.Create(&user)








db.Save(&user)

使用 FullSaveAssociations 更新关联

如果需要对关联数据进行完整更新(而不仅仅是更新外键引用),应使用 FullSaveAssociations 模式。


db.Session(&gorm.Session{FullSaveAssociations: true}).Updates(&user)

使用 FullSaveAssociations 可确保模型的完整状态(包括其所有关联)反映到数据库中,从而在整个应用程序中维护数据完整性和一致性。

跳过自动创建/更新

GORM 提供了灵活性,允许在创建或更新操作时跳过关联的自动保存。这可以通过 Select 或 Omit 方法实现,它们允许您精确指定哪些字段或关联应该包含或排除在操作中。

使用 Select 包含特定字段

Select 方法允许您指定模型的哪些字段应该被保存,这意味着只有选定的字段会被包含在 SQL 操作中。

user := User{
  
}


db.Select("Name").Create(&user)

使用 Omit 排除字段或关联

相反,Omit 允许您在保存模型时排除某些字段或关联。


db.Omit("BillingAddress").Create(&user)


db.Omit(clause.Associations).Create(&user)

注意:
对于多对多关联,GORM 会在创建联表引用之前对关联进行 upsert。要跳过此 upsert 操作,请使用 Omit 加上关联名称后跟 .*:

db.Omit("Languages.*").Create(&user)


要同时跳过关联及其引用的创建:

db.Omit("Languages").Create(&user)

通过使用 Select 和 Omit,您可以精细调整 GORM 如何处理模型的创建或更新,从而控制关联的自动保存行为。

选择/排除关联字段

在 GORM 中,创建或更新记录时,您可以使用 Select 和 Omit 方法来专门包含或排除关联模型的某些字段。

使用 Select,您可以指定保存主模型时应包含关联模型的哪些字段。这对于选择性保存关联的部分内容特别有用。

相反,Omit 允许您排除关联模型的某些字段不被保存。当您希望阻止关联的特定部分被持久化时,这非常有用。

user := User{
  Name:            "jinzhu",
  BillingAddress:  Address{Address1: "Billing Address - Address 1", Address2: "addr2"},
  ShippingAddress: Address{Address1: "Shipping Address - Address 1", Address2: "addr2"},
}


db.Select("BillingAddress.Address1", "BillingAddress.Address2").Create(&user)



db.Omit("BillingAddress.Address2", "BillingAddress.CreatedAt").Create(&user)

删除关联

GORM 允许在删除主记录时使用 Select 方法删除特定的关联关系(has one、has many、many2many)。此功能对于维护数据库完整性和确保删除时相关数据得到适当管理特别有用。

您可以使用 Select 指定哪些关联应随主记录一起删除。


db.Select("Account").Delete(&user)


db.Select("Orders", "CreditCards").Delete(&user)


db.Select(clause.Associations).Delete(&user)


db.Select("Account").Delete(&users)

注意:
需要注意的是,只有当被删除记录的主键不为零时,关联才会被删除。GORM 使用这些主键作为条件来删除选定的关联。

db.Select("Account").Where("name = ?", "jinzhu").Delete(&User{})

db.Select("Account").Where("name = ?", "jinzhu").Delete(&User{ID: 1})

db.Select("Account").Delete(&User{ID: 1})

关联模式

GORM 中的关联模式提供了多种辅助方法来处理模型之间的关系,提供了一种高效的管理关联数据的方式。

要启动关联模式,需要指定源模型和关系的字段名称。源模型必须包含主键,关系的字段名称应匹配一个已存在的关联。

var user User
db.Model(&user).Association("Languages")

error := db.Model(&user).Association("Languages").Error

查找关联

检索关联记录,可附带或不附带额外条件。


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)

追加关联

为 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"})

替换关联

用新的关联替换当前关联。


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

db.Model(&user).Association("Languages").Replace(Language{Name: "DE"}, languageEN)

删除关联

移除源与参数之间的关系,仅删除引用。


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

db.Model(&user).Association("Languages").Delete(languageZH, languageEN)

清除关联

移除源与关联之间的所有引用。


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

统计关联

获取当前关联的数量,可附带或不附带条件。


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


codes := []string{"zh-CN", "en-US", "ja-JP"}
db.Model(&user).Where("code IN ?", codes).Association("Languages").Count()

批量数据处理

关联模式允许您批量处理多条记录的关系,包括查找、追加、替换、删除和统计关联数据的操作。

  • 查找关联:检索一组记录的关联数据。
db.Model(&users).Association("Role").Find(&roles)
  • 删除关联:在多条记录中移除特定关联。
db.Model(&users).Association("Team").Delete(&userA)
  • 统计关联:获取一批记录的关联数量。
db.Model(&users).Association("Team").Count()
  • 追加/替换关联:管理多条记录的关联。请注意需要使参数长度与数据匹配。
var users = []User{user1, user2, user3}



db.Model(&users).Association("Team").Append(&userA, &userB, &[]User{userA, userB, userC})



db.Model(&users).Association("Team").Replace(&userA, &userB, &[]User{userA, userB, userC})

删除关联记录

在 GORM 中,关联模式中的 Replace、Delete 和 Clear 方法主要影响外键引用,而不是关联记录本身。理解和管理这种行为对数据完整性至关重要。

  • 引用更新:这些方法将关联的外键设置为 null,从而有效地移除源模型与关联模型之间的链接。
  • 不删除物理记录:实际的关联记录在数据库中保持不变。

使用 Unscoped 修改删除行为

对于需要实际删除关联记录的场景,Unscoped 方法可以改变这种行为。

  • 软删除:将关联记录标记为已删除(设置 deleted_at 字段),而不从数据库中移除它们。
db.Model(&user).Association("Languages").Unscoped().Clear()
  • 永久删除:从数据库中物理删除关联记录。

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

关联标签

GORM 中的关联标签用于指定模型之间的关联如何被处理。这些标签定义了关系的详细信息,如外键、引用和约束。了解这些标签对于有效设置和管理关系至关重要。

标签描述
foreignKey指定当前模型中用作联表外键的列名。
references指示联表外键映射到的引用表中的列名。
polymorphic定义多态类型,通常为模型名称。
polymorphicValue设置多态值,通常为表名,如未另行指定。
many2many指定多对多关系使用的联表名称。
joinForeignKey标识联表中映射回当前模型表的外键列。
joinReferences指向联表中链接到引用模型表的外键列。
constraint指定关联的关系约束,如 OnUpdate、OnDelete。

GitHub tag (latest SemVer)

评论

登录后参与评论

正在加载评论…