
字节笔记本
2026年10月7日 · 约 2 分钟读完
关联标签里仍然写着级联约束
学生和课程用中间表 student_courses。两边的切片标签是 many2many:student_courses。预加载写成 Preload("Courses") 和 Preload("Students")。用户说不用外键,接着问那是不是不能预加载。回答说预加载可以留下,并给连接表写了 joinForeignKey 和 joinReferences。这两个名字指定的是中间表里的列,用来拼关联查询。
注释和标签互相矛盾
中间模型 StudentCourse 上有学生和课程两个字段。注释写「添加关联,但不使用外键约束」。标签是 foreignKey:StudentID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE。constraint 这一段会让迁移去创建外键,删除和更新都级联。这就是用户说的「这不还是外键」。列名 StudentID、CourseID 可以只做普通索引。索引和级联外键不是同一件事。gorm:"index" 已经写在这两列上。
状态字段是枚举:待处理、处理中、已完成、已取消,默认待处理。枚举不依赖那条级联。

many2many 上的 joinForeignKey 和结构体字段上的 foreignKey 也不是同一个标签。前者告诉预加载去中间表的哪一列找。后者配上 constraint,才是数据库里的外键。去掉外键之后,预加载仍然按列的值去找行。找不到时结果是空切片,不会因为没有级联就无法查询。
用户要的是关联查询,不是删除学生时连带删课程。级联写上之后,删一边会按约束动另一边。这和「不用外键」相反。
预加载读的是列
Preload("Courses") 按中间表把课程填进切片。它需要中间表有学生和课程两列,不需要这两列在数据库里被声明成外键。把 constraint 留在标签里,迁移仍会去建约束。注释改了,标签没改,生成的表还是带外键。

不要外键,就去掉 constraint 以及会创建约束的那一段。中间表的列保留给预加载。注释不能和标签相反。



