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)
  
}

错误信息

Capture2

Capture


更多关于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)
}

关键修改点:

  1. Child *User 改为 Children []User,因为一个父级可以有多个子级
  2. Parent uint 改为 ParentID *uint,使用指针允许NULL值(根节点没有父级)
  3. 使用 gorm:"foreignkey:ParentID" 标签明确指定外键字段
  4. 分别创建父级和子级记录,确保外键引用有效

如果使用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 方法。

回到顶部