官方文档上对于外键是如此描述的:
凝练一下关键词:必须存在外键,默认外键(约定)是拥有者类型+主字段名
我们尝试一下:
type Staff struct {
//gorm.Model
ID int
Name string
CompanyID int
Company Company
}
type Company struct {
ID int
Name string
CompanyAge int
}
我们自动迁移一下
func main() {
dsn := "root:密码@tcp(127.0.0.1:3306)/db_Golang?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
NamingStrategy: schema.NamingStrategy{
SingularTable: true,
},
})
if err != nil {
fmt.Println("gorm ,Open failed ,err:",err)
}
db.AutoMigrate(
Staff{},
Company{}, )
}
得到如下sql语句,我们主要观察的是staff的创建,所以之后我们只放staff的sql语句
CREATE TABLE `company`
(`id` bigint AUTO_INCREMENT,
`name` longtext,
`company` bigint,
PRIMARY KEY (`id`));
CREATE TABLE `staff`
(`id` bigint AUTO_INCREMENT,
`name` longtext,
`company_id` bigint,
PRIMARY KEY (`id`),
CONSTRAINT `fk_staff_company` FOREIGN KEY (`company_id`) REFERENCES `company`(`id`))
我们发现默认主键都为ID字段,符合gorm约定,staff创建物理外键为company_id针对company表的ID字段,貌似符合官方文档所描述的情况了。
但我们先思考几个需要排除的点,再进行测试。
验证:默认外键字段的命名规则:拥有者类型+主字段名
1.若主键不是ID字段,外键是跟随xxxID,还是xxx主键
2.staff表中若没有ComanyID字段,只有Comany复杂字段
3.若Comany复杂字段改名,外键是跟随类型Comany,还是跟随字段名一起更改?
针对以上几点对数据进行了微调,做了几组测试:
type Staff struct {
ID int
Name string `gorm:"primaryKey"`
Company123Name int
Company123 Company
}
type Company struct {
ID int
Name string `gorm:"primaryKey"`
CompanyAge int
}
这里就不一一发结果了直接报结论:
1.主键不是ID时,可以用Company类型的字段+ID作为外键(即使没有ID字段),还可以用Company类型的字段+主键字段作为外键
2.若复杂字段没有符合的外键字段,则无法进行迁移,会报错。但若在复杂字段后声明嵌套字段tag:`gorm:"embedded"`虽可以运行,但本质就不一样了。
3.复杂字段改名,则外键要跟着一起改。是跟随字段名的,并不是类型。
直接看源码也可以看到结论,或直接去修改外键的命名策略。这点之后再进行探究。
有些文档语义不明,还是亲身实践一下比较好