Golang递归表中外键约束失败问题
Golang递归表中外键约束失败问题 我正在尝试在递归表中添加外键,并启用 onDelete 和 onUpdate 的 CASCADE 模式,以便在删除父级时删除所有子级(更新时同理)
package main
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
type User struct {
gorm.Model
Name string
Child *User `gorm:"Foreignkey:Parent"`
Parent uint
}
func main() {
db, err := gorm.Open("mysql", "root@/testdb")
if err != nil {
panic("failed to connect database")
}
defer db.Close()
// Migrate the schema
db.AutoMigrate(&User{})
db.Model(&User{}).AddForeignKey("parent","users(id)","CASCADE","CASCADE")
// Create
u := User{Name: "Parent", Child: &User{Name:"Child"}}
db.Save(&u)
}
错误信息


更多关于Golang递归表中外键约束失败问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
3 回复
我尝试了这个方法,确实有效,感谢
u := User{Name: "Parent"}
db.Save(&u)
u2 := User{Name: "Child", Parent: &u.ID}
db.Save(&u2)
更多关于Golang递归表中外键约束失败问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
以下是一些想法。如果先添加子记录再添加父记录,这样能正常工作吗?或者反过来操作?如果先添加子记录,那么父记录在数据库中还不存在,约束条件就会失败。你能让gorm输出它生成的所有SQL语句吗:
db.LogMode(true)
然后观察它是以什么顺序将用户添加到数据库中的。
在Golang中使用GORM处理递归表的外键约束时,需要正确定义模型关系和约束。根据你的代码,主要问题在于模型结构定义和外键约束设置不匹配。
以下是修正后的代码示例:
package main
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
)
type User struct {
gorm.Model
Name string
ParentID *uint // 使用指针类型允许NULL值
Children []User `gorm:"foreignkey:ParentID"` // 使用复数形式表示多个子项
}
func main() {
db, err := gorm.Open("mysql", "root@/testdb")
if err != nil {
panic("failed to connect database")
}
defer db.Close()
// 迁移schema
db.AutoMigrate(&User{})
// 添加外键约束
db.Model(&User{}).AddForeignKey("parent_id", "users(id)", "CASCADE", "CASCADE")
// 创建记录
parent := User{Name: "Parent"}
db.Save(&parent)
child := User{Name: "Child", ParentID: &parent.ID}
db.Save(&child)
}
关键修改点:
- 将
Child *User改为Children []User,因为一个父级可以有多个子级 - 将
Parent uint改为ParentID *uint,使用指针允许NULL值(根节点没有父级) - 使用
gorm:"foreignkey:ParentID"标签明确指定外键字段 - 分别创建父级和子级记录,确保外键引用有效
如果使用GORM v2,代码可以进一步简化:
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type User struct {
gorm.Model
Name string
ParentID *uint
Children []User `gorm:"foreignkey:ParentID;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
}
func main() {
dsn := "root@tcp(localhost:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&User{})
parent := User{Name: "Parent"}
db.Create(&parent)
child := User{Name: "Child", ParentID: &parent.ID}
db.Create(&child)
}
在GORM v2中,可以直接在结构体标签中定义级联约束,无需单独调用 AddForeignKey 方法。

