Golang中使用Gorm结构体时遇到的问题
Golang中使用Gorm结构体时遇到的问题 我正在开发一个简单的鸟类繁殖应用程序,毕竟学习新东西总得找个有趣的项目,对吧?😊
到目前为止,一切运行得都很顺利。我可以添加、编辑和删除鸟类信息。但当我尝试添加字段来关联鸟类与其父母时,问题就出现了。难点在于,我们并不总是能同时拥有鸟类及其父母的信息。我目前能想到的最佳结构如下:
type Bird struct {
gorm.Model
RingNo string `gorm:"not null"`
Species string `gorm:"not null"`
Color string `gorm:"not null"`
■■■ string `gorm:"not null"`
UserID uint `gorm:"not null"`
User User
FatherID *uint
Father *Bird `gorm:"foreignKey:FatherID;default:SET NULL"`
MotherID *uint
Mother *Bird `gorm:"foreignKey:MotherID;default:SET NULL"`
Notes []BirdNote `gorm:"foreignKey:BirdID"`
}
基本上,我想要实现的目标是让 FatherID 和 MotherID 可以为空。但无论我尝试什么方法,最终总是会遇到“违反键约束”的错误 😦
更多关于Golang中使用Gorm结构体时遇到的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
当我将所有内容都设置为字符串时,它可以工作。但那样我就必须手动填写父鸟ID和母鸟ID。在理想情况下,我可以通过下拉菜单将鸟与其父鸟和母鸟的脚环编号关联起来。(或者,如果我不知道父鸟和母鸟,就留空。)
// 代码部分保持原样,不翻译
更多关于Golang中使用Gorm结构体时遇到的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我尚未使用过GORM,但搜索“gorm foreign key nullable”时,我找到了以下两个看起来很有希望的链接:
- postgresql - How to insert a null foreign key in gorm? - Stack Overflow
- How to create nullable foreign key in gorm/v2 · Issue #3188 · go-gorm/gorm · GitHub
我无法确定哪个解决方案效果最好,甚至不确定你是否需要进一步调整它们,但我希望它们能对你有所帮助。祝你顺利。
在Golang中使用Gorm处理自引用外键时,确实需要特别注意外键约束。根据你的需求,正确的结构体定义应该如下:
type Bird struct {
gorm.Model
RingNo string `gorm:"not null"`
Species string `gorm:"not null"`
Color string `gorm:"not null"`
UserID uint `gorm:"not null"`
User User
FatherID *uint `gorm:"default:null"`
Father *Bird `gorm:"foreignKey:FatherID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
MotherID *uint `gorm:"default:null"`
Mother *Bird `gorm:"foreignKey:MotherID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
Notes []BirdNote `gorm:"foreignKey:BirdID"`
}
关键点在于:
FatherID和MotherID使用*uint指针类型,配合gorm:"default:null"标签- 在关联标签中明确指定外键约束行为:
constraint:OnUpdate:CASCADE,OnDelete:SET NULL;
创建数据库迁移时,需要确保外键约束允许NULL值:
// 创建表时的SQL示例
db.Exec(`
CREATE TABLE birds (
id SERIAL PRIMARY KEY,
ring_no VARCHAR(255) NOT NULL,
species VARCHAR(255) NOT NULL,
color VARCHAR(255) NOT NULL,
user_id INTEGER NOT NULL,
father_id INTEGER,
mother_id INTEGER,
created_at TIMESTAMP,
updated_at TIMESTAMP,
deleted_at TIMESTAMP,
FOREIGN KEY (father_id) REFERENCES birds(id) ON DELETE SET NULL,
FOREIGN KEY (mother_id) REFERENCES birds(id) ON DELETE SET NULL
)
`)
插入数据时,对于没有父母的鸟类,将FatherID和MotherID设为nil:
// 创建没有父母的鸟
birdWithoutParents := Bird{
RingNo: "RING001",
Species: "Canary",
Color: "Yellow",
UserID: 1,
FatherID: nil,
MotherID: nil,
}
// 创建有父母的鸟
fatherID := uint(1)
motherID := uint(2)
birdWithParents := Bird{
RingNo: "RING002",
Species: "Canary",
Color: "Yellow",
UserID: 1,
FatherID: &fatherID,
MotherID: &motherID,
}
db.Create(&birdWithoutParents)
db.Create(&birdWithParents)
查询时使用Preload加载关联:
var bird Bird
db.Preload("Father").Preload("Mother").First(&bird, 1)
// 检查是否有父母
if bird.Father != nil {
fmt.Printf("父亲: %s\n", bird.Father.RingNo)
}
if bird.Mother != nil {
fmt.Printf("母亲: %s\n", bird.Mother.RingNo)
}
这样配置后,当删除父鸟时,子鸟的对应父ID会自动设置为NULL,不会违反外键约束。

