Has Many
Has Many
has many
与另一个模型建立了一对多的连接。 不同于 has one
,拥有者可以有零或多个关联模型。
例如,您的应用包含 user 和 credit card 模型,且每个 user 可以有多张 credit card。
// User 有多张 CreditCard,UserID 是外键 type User struct { gorm.Model CreditCards []CreditCard } type CreditCard struct { gorm.Model Number string UserID uint }
重写外键
要定义 has many
关系,同样必须存在外键。 默认的外键名是拥有者的类型名加上其主键字段名
例如,要定义一个属于 User
的模型,则其外键应该是 UserID
。
此外,想要使用另一个字段作为外键,您可以使用 foreignKey
标签自定义它:
type User struct { gorm.Model CreditCards []CreditCard `gorm:"foreignKey:UserRefer"` } type CreditCard struct { gorm.Model Number string UserRefer uint }
重写引用
GORM 通常使用拥有者的主键作为外键的值。 对于上面的例子,它是 User
的 ID
字段。
为 user 添加 credit card 时,GORM 会将 user 的 ID
字段保存到 credit card 的 UserID
字段。
同样的,您也可以使用标签 references
来更改它,例如:
type User struct { gorm.Model MemberNumber string CreditCards []CreditCard `gorm:"foreignKey:UserNumber;references:MemberNumber"` } type CreditCard struct { gorm.Model Number string UserNumber string }
多态关联
GORM 为 has one
和 has many
提供了多态关联支持,它会将拥有者实体的表名、主键都保存到多态类型的字段中。
type Dog struct { ID int Name string Toys []Toy `gorm:"polymorphic:Owner;"` } type Toy struct { ID int Name string OwnerID int OwnerType string } db.Create(&Dog{Name: "dog1", Toy: []Toy{{Name: "toy1"}, {Name: "toy2"}}}) // INSERT INTO `dogs` (`name`) VALUES ("dog1") // INSERT INTO `toys` (`name`,`owner_id`,`owner_type`) VALUES ("toy1","1","dogs"), ("toy2","1","dogs")
您可以使用标签 polymorphicValue
来更改多态类型的值,例如:
type Dog struct { ID int Name string Toys []Toy `gorm:"polymorphic:Owner;polymorphicValue:master"` } type Toy struct { ID int Name string OwnerID int OwnerType string } db.Create(&Dog{Name: "dog1", Toys: []Toy{{Name: "toy1"}, {Name: "toy2"}}}) // INSERT INTO `dogs` (`name`) VALUES ("dog1") // INSERT INTO `toys` (`name`,`owner_id`,`owner_type`) VALUES ("toy1","1","master"), ("toy2","1","master")
Has Many 的 CURD
查看 关联模式 获取 has many 相关的用法
预加载
GORM 可以通过 Preload
预加载 has many 关联的记录,查看 预加载 获取详情
自引用 Has Many
注意与has one 区别,这里会产生外键关系,同时要添加*,否者报错
type User struct { gorm.Model Name string ManagerID *uint Team []*User `gorm:"foreignkey:ManagerID"` }
外键约束
你可以通过为标签 constraint
配置 OnUpdate
、OnDelete
实现外键约束,在使用 GORM 进行迁移时它会被创建,例如:
type User struct { gorm.Model CreditCards []CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` } type CreditCard struct { gorm.Model Number string UserID uint }
你也可以在删除记录时通过 Select
来删除 has many 关联的记录,查看 Delete with Select 获取详情