先聊聊Gorm外键的设置:
我个人比较喜欢tag直接设置,但今天做项目就出了问题,tag一直失效。但找不到原因在哪里。网上的答案只有用AddForeignKey方法去手动添加外键。但我想搞清楚为什么tag会失效
关于tag的设置,在gorm中有如下几个设置:
MANY2MANY 指定连接表 FOREIGNKEY 设置外键 references 指定引用的表中的字段 ASSOCIATION_FOREIGNKEY 设置当前表中关联的外键字段 POLYMORPHIC 指定多态类型 POLYMORPHIC_VALUE 指定多态值 JOINTABLE_FOREIGNKEY 指定连接表的外键 ASSOCIATION_JOINTABLE_FOREIGNKEY 指定连接表的关联外键 SAVE_ASSOCIATIONS 是否自动完成 save 的相关操作 ASSOCIATION_AUTOUPDATE 是否自动完成 update 的相关操作 ASSOCIATION_AUTOCREATE 是否自动完成 create 的相关操作 ASSOCIATION_SAVE_REFERENCE 是否自动完成引用的 save 的相关操作 PRELOAD 是否自动完成预加载的相关操作
表与表之间的关系也就那么三个:
- 一对一:个人和身份证
- 多对一:学生对班级
- 多对多:学生对老师
针对不同的情况,GORM对不同的表关系做了不同的策略
一对一:
我们可以如下设置:
type Staff struct {
ID int
Name string `gorm:"primaryKey"` //实际测试,Company123Name也可以当自动外键
Company123ID int //默认外键,gorm约定:连接companies表id字段 目标表名+ID (这个'ID'是固定的,不是当前或目标的主键字段,目标表名可以有任意前缀,不影响)
Company123 Company /*`gorm:"embedded"`*/ //该字段在创建时,会被忽略。除非有embedded字段,表示嵌套。会初始化company表的不重复字段
}
type Company struct {
ID int
Name string `gorm:"primaryKey"` //测试外键是否会连接主键
CompanyAge int
}
我测试了好多次,有如下总结:
一对一关系的设置时,从结构体有主结构体的复杂字段(如Staff中有Company类型字段)
并根据默认外键的约定:同时有该字段名+当前表主键名的字段(或ID)会被当作外键去跟主结构体主键关联
一对多:
type Student struct {
ID string
ClassId string
Class Class
Name string
//Teachers []Teacher `gorm:"many2many:stu_tea"`
}
//一对多关系:一个班级中有多个学生
type Class struct {
ID int
Students []Student `gorm:"FOREIGNKEY:ClassId;"`
}
一对多的关系设置时,主结构有从结构的切片复杂字段
其次需要从结构要有外键字段,这时根据默认外键约定 ,我们需要两步
1.在从结构添加主结构复杂字段,以满足默认外键约定
2.在主结构的切片字段上添加tag:FOREIGNKEY:从结构字段 以指定外键字段
我们可以通过1,来达成反向搜索的目的
多对多:
type Student struct {
ID string
//ClassId string
//Class Class
Name string
Teachers []Teacher `gorm:"many2many:stu_tea"`
}
//多对多:老师跟学生多对多的关系
type Teacher struct {
ID string
Name string
Students []Student `gorm:"many2many:stu_tea"`
}
感动哭了,多对多的关系是最简单的。
1.我们需要在俩结构中各放一个外表的切片字段
2.其次我们需要给该字段(任意一个)设置gorm:"many2many:中间表名"
当我们通过 db.AutoMigrate() 方法去迁移数据库时,gorm会自动创建一个中间表,来自动关联两表
最后,虽然这些问题看起来比较简单,但整理起来也很花时间。最重要的是不断求知的思考过程,愿我们都能前程似锦
参考:GORM-学习 - 掘金 (juejin.cn)但其关于外键部分结论是有错误的,论证如上,版本问题?