多态
多态只支持一对一和一对多!
多态只存在has one和has many的关系里面,多态的结构体数据不可用同时被多人拥有
- polymorphic 指定多态类型,比如模型名
- polymorphicValue 指定多态值、默认表名
夹子拥有小风车,御姐也有小风车,如果又来一个别人,总不能在小风车里面增加多个字段吧,所有这里用到多态,用polymorphic:Owner指定多态,则小风车只需要2个字段即可实现多态(OwnerType,OwnerID)
type Jiazi struct { Id uint Name string Xiaofengche Xiaofengche `gorm:"polymorphic:Owner"` } type Yujie struct { Id uint Name string Xiaofengche Xiaofengche `gorm:"polymorphic:Owner"` } type Xiaofengche struct { Id uint Name string OwnerType string OwnerID uint } func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&Jiazi{}, &Yujie{}, &Xiaofengche{}) }
给数据库中插入数据,两个字段确定到不同的表中,这就是多态。这里ownertype是结构体名的复数
func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&Jiazi{}, &Yujie{}, &Xiaofengche{}) db.Create(&Jiazi{Name: "夹子", Xiaofengche: Xiaofengche{Name: "小风车"}}) db.Create(&Yujie{Name: "御姐", Xiaofengche: Xiaofengche{Name: "大风车"}}) }
下面通过polymorphicValue来指定ownertype存的值,可以看到owner_type的值变成我们指定的值了
type Jiazi struct { Id uint Name string Xiaofengche Xiaofengche `gorm:"polymorphic:Owner;polymorphicValue:JZ"` } type Yujie struct { Id uint Name string Xiaofengche Xiaofengche `gorm:"polymorphic:Owner;polymorphicValue:YJ"` } type Xiaofengche struct { Id uint Name string OwnerType string OwnerID uint } func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&Jiazi{}, &Yujie{}, &Xiaofengche{}) db.Create(&Jiazi{Name: "夹子", Xiaofengche: Xiaofengche{Name: "小风车"}}) db.Create(&Yujie{Name: "御姐", Xiaofengche: Xiaofengche{Name: "大风车"}}) }
下面看看has many的情况
type Jiazi struct { Id uint Name string Xiaofengches []Xiaofengche `gorm:"polymorphic:Owner;polymorphicValue:JZ"` } type Xiaofengche struct { Id uint Name string OwnerType string OwnerID uint } func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&Jiazi{}, &Xiaofengche{}) db.Create(&Jiazi{Name: "夹子", Xiaofengches: []Xiaofengche{ {Name: "小风车1"}, {Name: "小风车2"}, {Name: "小风车3"}, }}) }
关联标签
外键和引用
一对多的形式
这里指定了foreignKey为FkId去关联默认的Id
type Jiazi struct { Id uint Name string Xiaofengches []Xiaofengche `gorm:"foreignKey:FkId"` } type Xiaofengche struct { Id uint Name string FkId uint } func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&Jiazi{}, &Xiaofengche{}) db.Create(&Jiazi{Name: "夹子", Xiaofengches: []Xiaofengche{ {Name: "小风车1"}, {Name: "小风车2"}, {Name: "小风车3"}, }}) }
而如果不想关联JiaZi表的id,想关联name字段呢,则用references,需要注意的是,作为外键或者被关联的键,这个键必须是索引且唯一
type Jiazi struct { Id uint Name string `gorm:"unique"` Xiaofengches []Xiaofengche `gorm:"foreignKey:JzName;references:Name"` } type Xiaofengche struct { Id uint Name string JzName string `gorm:"unique"` } func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&Jiazi{}, &Xiaofengche{}) db.Create(&Jiazi{Name: "夹子", Xiaofengches: []Xiaofengche{ {Name: "小风车1"}, {Name: "小风车2"}, {Name: "小风车3"}, }}) }
多对多
在多对多关系中,外键指定为本结构体的字段,引用指定为另一个结构体的字段即可
type Jiazi struct { Id uint `gorm:"autoIncrement"` Name string `gorm:"index;unique;size:191"` Xiaofengches []Xiaofengche `gorm:"many2many:jiazi_fengche;foreignKey:Name;references:FcName"` } type Xiaofengche struct { Id uint `gorm:"autoIncrement"` FcName string `gorm:"index;unique;size:191"` } func main() { db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{}) db.AutoMigrate(&Jiazi{}, &Xiaofengche{}) db.Create(&Jiazi{Name: "夹子", Xiaofengches: []Xiaofengche{ {FcName: "小风车1"}, {FcName: "小风车2"}, {FcName: "小风车3"}, }}) }
现在,我们使用joinForeignKey 和joinForeignKey 修改字段名称
Xiaofengches []Xiaofengche `gorm:"many2many:jiazi_fengche;foreignKey:Name;joinForeignKey:A;references:FcName;joinReferences:B"`