踩坑:
看到gorm文档,应该是在tag标签中写入foreignkey可以设置外键,但是不能达到预期效果
type User struct {
gorm.Model
LanguagesID int`gorm:"ForeignKey:Language"`
//通过标签设置外键,失效,不能映射到数据库中
}
type Language struct {
gorm.Model
Name string
}
介绍一个函数
db.Model().AddForeignKey()//需要使用已经存在的表
Model()
db.Model().AddForeignKey()
//Model()函数传入那个表需要的外键
//例如开头的user表和language表,外键在user表中,则需要传入User结构体的地址
db.Model(&User{}).AddForeignKey()
AddForeignKey()
函数需要四个参数:
- 外键键名(迁移数据库之后生成的字段名,不是结构体中的字段名)
- 关联的外键:关联的表名(字段名),同样都是生成的数据库的表名和字段名
- 删除时的状态:set null ,no action,cascade,restrict,其中restrict和no action相同,如果子表有关联数据,父表对应数据不能进行删除,cascade模式:如果删除父表数据,则对应的子表数据也相应删除,set null模式:如果父表删除数据,对应的子表的数据的外键被设置为null,但是相应的这个模式要求子表外键字段可以为null
- 更新时表的状态,与删除时的四种状态相同
type User struct {
gorm.Model
LanguagesID int `gorm:"type:int unsigned"`
}
type Language struct {
gorm.Model
Name string
}
func migrate(){
db:=gorm.open("mysql","root:@tcp(:3306)/database?charset=utf8")
db.AutoMigrate(&Language{},&User{})
db.Model(&User{}).AddForeignKey("languages_id","languages(id)","CASCADE","CASCADE")
//在user表中生成外键为languages_id字段,对应的外表为languages的id字段languages(id),模式为CASCADE
}
易错点
gorm中有嵌套的gorm.Model结构体,其中有id字段
type User struct {
gorm.Model
LanguagesID int
}
type Language struct {
gorm.Model
Name string
}
db.Model(&User{}).AddForeignKey("languages_id", "languages(id)", "RESTRICT", "RESTRICT")
//需要注意,如果这种情况迁移数据库,不会成功
//原因:gorm.Model中的id字段为int unsigned类型,如果两个字段类型不相对应,则不能成为两个表对应字段的外键
更改之后
type User struct {
gorm.Model
LanguagesID int`gorm:"type:int unsigned"`
}
type Language struct {
gorm.Model
Name string
}
//此时可以迁移数据库