Has One

has one 与另一个模型建立一对一的关联,但它和一对一关系有些许不同。 这种关联表明一个模型的每个实例都包含或拥有另一个模型的一个实例。

例如,您的应用包含 user 和 credit card 模型,且每个 user 只能有一张 credit card。

  1. // User 有一张 CreditCard,CreditCardID 是外键
    type User struct {
    gorm.Model
    CreditCard CreditCard
    }

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

重写外键

对于 has one 关系,同样必须存在外键字段。拥有者将把属于它的模型的主键保存到这个字段。

这个字段的名称通常由 has one 模型的类型加上其 主键 生成,对于上面的例子,它是 UserID

为 user 添加 credit card 时,它会将 user 的 ID 保存到自己的 UserID 字段。

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

  1. type User struct {
    gorm.Model
    CreditCard CreditCard `gorm:"foreignKey:UserName"`
    // 使用 UserName 作为外键
    }

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

重写引用

默认情况下,拥有者实体会将 has one 对应模型的主键保存为外键,您也可以修改它,用另一个字段来保存,例如下个这个使用 Name 来保存的例子。

您可以使用标签 references 来更改它,例如:

  1. type User struct {
    gorm.Model
    Name string `sql:"index"`
    CreditCard CreditCard `gorm:"foreignkey:UserName;references:name"`
    }

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

多态关联

GORM 为 has onehas many 提供了多态关联支持,它会将拥有者实体的表名、主键值都保存到多态类型的字段中。

  1. 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
    }

    db.Create(&Dog{Name: "dog1", Toy: Toy{Name: "toy1"}})
    // INSERT INTO `dogs` (`name`) VALUES ("dog1")
    // INSERT INTO `toys` (`name`,`owner_id`,`owner_type`) VALUES ("toy1","1","dogs")

您可以使用标签 polymorphicValue 来更改多态类型的值,例如:

  1. type Dog struct {
    ID int
    Name string
    Toy Toy `gorm:"polymorphic:Owner;polymorphicValue:master"`
    }

    type Toy struct {
    ID int
    Name string
    OwnerID int
    OwnerType string
    }

    db.Create(&Dog{Name: "dog1", Toy: Toy{Name: "toy1"}})
    // INSERT INTO `dogs` (`name`) VALUES ("dog1")
    // INSERT INTO `toys` (`name`,`owner_id`,`owner_type`) VALUES ("toy1","1","master")

Has One 的 CURD

查看 关联模式 获取 has one 相关的用法

预加载

GORM 可以通过 PreloadJoins 预加载 has one 关联的记录,查看 预加载 获取详情

自引用 Has One

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

外键约束

你可以通过为标签 constraint 配置 OnUpdateOnDelete 实现外键约束,在使用 GORM 进行迁移时它会被创建,例如:

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

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

你也可以在删除记录时通过 Select 来删除关联的记录,查看 Delete with Select 获取详情