关联

一对一

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

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

一对一(Has One)

has one 关联建立与另一个模型的一对一连接,但其语义(及结果)有所不同。该关联表示一个模型的每个实例包含或拥有另一个模型的一个实例。

例如,如果您的应用包含用户和信用卡,并且每个用户只能有一张信用卡。

声明


type User struct {
  gorm.Model
  CreditCard CreditCard
}

type CreditCard struct {
  gorm.Model
  Number string
  UserID uint
}

查询


func GetAll(db *gorm.DB) ([]User, error) {
  var users []User
  err := db.Model(&User{}).Preload("CreditCard").Find(&users).Error
  return users, err
}

覆盖外键

对于 has one 关系,还必须存在一个外键字段,拥有者会将它所属于的模型的主键保存到该字段中。

该字段的名称通常由 has one 模型的类型加上其 主键 生成,在上面的例子中就是 UserID。

当你把一张信用卡给用户时,它会将用户的 ID 保存到其 UserID 字段中。

如果你想使用另一个字段来保存该关系,可以用 foreignKey 标签进行更改,例如:

type User struct {
  gorm.Model
  CreditCard CreditCard `gorm:"foreignKey:UserName"`
  
}

type CreditCard struct {
  gorm.Model
  Number   string
  UserName string
}

覆盖引用

默认情况下,被拥有的实体会将 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
}

一对一的增删改查

有关使用 has one 关系的操作,请查看 关联模式

预加载

GORM 允许使用 Preload 或 Joins 预加载 has one 关联,详见预加载(Eager loading)

自引用一对一

type User struct {
  gorm.Model
  Name      string
  ManagerID *uint
  Manager   *User
}

外键约束

你可以通过 constraint 标签设置 OnUpdate、OnDelete 约束,这些约束会在使用 GORM 迁移时被创建,例如:

type User struct {
  gorm.Model
  CreditCard CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
}

type CreditCard struct {
  gorm.Model
  Number string
  UserID uint
}

在删除时,你还允许使用 Select 删除选定的一对一关联,详情请查看 使用 Select 删除

GitHub tag (latest SemVer)

评论

登录后参与评论

正在加载评论…