英文:
GORM Error on insert or update on table violates foreign key constraint
问题
我有以下一组 GORM 模型,其中有两个一对多关系的订单:
type Order struct {
ID string `gorm:"column:id"`
ClientID string `gorm:"primaryKey;column:client_id"`
Name string `gorm:"column:name"`
Albums []Album `gorm:"foreignKey:RequestClientID"`
}
type Album struct {
AlbumID string `gorm:"primaryKey;column:album_id"`
RequestClientID string `gorm:"foreignKey:ClientID;column:request_client_id"`
Pictures []Picture `gorm:"foreignKey:AlbumID"`
}
type Picture struct {
PictureID string `gorm:"primaryKey;column:picture_id"`
AlbumID string `gorm:"foreignKey:AlbumID;column:album_id"`
Description string `gorm:"column:description"`
}
当我尝试插入以下数据时,我会收到错误消息 pq: insert or update on table "albums" violates foreign key constraint "fk_orders_albums"
。
test := Order{
ID: "abc",
ClientID: "client1",
Name: "Roy",
Albums: []Album{
{
AlbumID: "al_1",
Pictures: []Picture{
{
PictureID: "pic_1",
Description: "test pic",
},
},
},
},
}
gormDB.Save(&test)
我按照这个类似问题上的解决方案进行了尝试,但似乎无法解决:https://stackoverflow.com/questions/71129151/golang-gorm-error-on-insert-or-update-on-table-violates-foreign-key-contraint
英文:
I have the following set of GORM models, with 2 orders of one-to-many relations:
type Order struct {
ID string `gorm:"column:id"`
ClientID string `gorm:"primaryKey;column:client_id"`
Name string `gorm:"column:name"`
Albums []Album `gorm:"foreignKey:RequestClientID"`
}
type Album struct {
AlbumID string `gorm:"primaryKey;column:album_id"`
RequestClientID string `gorm:"foreignKey:ClientID;column:request_client_id"`
Pictures []Picture `gorm:"foreignKey:AlbumID"`
}
type Picture struct {
PictureID string `gorm:"primaryKey;column:picture_id"`
AlbumID string `gorm:"foreignKey:AlbumID;column:album_id"`
Description string `gorm:"column:description"`
}
When I attempt to insert data as follows, I get the error pq: insert or update on table "albums" violates foreign key constraint "fk_orders_albums"
.
test := Order{
ID: "abc",
ClientID: "client1",
Name: "Roy",
Albums: []Album{
{
AlbumID: "al_1",
Pictures: []Picture{
{
PictureID: "pic_1",
Description: "test pic",
},
},
},
},
}
gormDB.Save(&test)
I followed the solution on this similar question, but can't seem to get it to work: https://stackoverflow.com/questions/71129151/golang-gorm-error-on-insert-or-update-on-table-violates-foreign-key-contraint
答案1
得分: 1
根据你的实体模型,你的架构应该是这样的:
- Orders 表是父表,不依赖于任何表
- Albums 表有一个外键 request_client_id,它引用了 orders 表的 client_id 列
- Picture 表有一个外键 album_id,它引用了 albums 表的 album_id 列
根据我在 gorm 文档中的探索,在这里,结构体中的对象将被视为第一个关联。所以,你的结构体将首先执行对 albums
的插入,这违反了外键架构(期望的是先执行对 orders 表的插入,然后是 albums 表)。
但是,如果你想强制使用你的架构,你可以使用 gorm 的关联特性。
以下是使用关联的思路:
高层次的预期查询:
- 插入 orders 表
- 插入 albums 表
- 插入 pictures 表
关联的思路:
- 让 Orders 结构体中的 Albums 字段值为空
- 将关联 Albums 添加到 Orders 模型中
- 由于 Albums 中还有另一个关联,使用 FullSaveAssociation 配置
以下是示例代码:
picture := []Picture{
{
PictureID: "pic_1",
Description: "test pic",
},
}
albums := []Album{
{
ID: "al_1",
Pictures: picture,
RequestClientID: "",
},
}
orders := Order{
ID: "abc",
ClientID: "client1",
Name: "Roy",
}
if err := gormDB.Save(orders).Error; err != nil {
return
}
if err := gormDB.Session(&gorm.Session{FullSaveAssociations: true}).Model(&orders).Association("Albums").Append(albums); err != nil {
return
}
完整的代码可以在这里找到。
英文:
Based on your entity model, Your schema would be like this:
- Orders table is parent table, didn't depend to any table
- Albums table has foreign key request_client_id which refer to orders table column client_id
- Picture table has foreign key album_id which is refer to albums table column album_id
Based on my exploration in gorm documentation here, object in struct will be examine as first association. so, your struct will execute insert to albums
first which it violate foreign key schema (expect: insert to orders table should be executed before albums).
But if you want to force using your schema, you can use gorm Association feature.
Here is the idea of using Association:
Expected Query in high level:
- Insert to orders table
- Insert to albums table
- Insert to pictures table
Association Ideas:
- Let Albums field value in Orders struct empty
- Append Association Albums to Orders model
- Since there have another association in Albums, use configuration FullSaveAssociation
Here is the following code:
picture := []Picture{
{
PictureID: "pic_1",
Description: "test pic",
},
}
albums := []Album{
{
ID: "al_1",
Pictures: picture,
RequestClientID: "",
},
}
orders := Order{
ID: "abc",
ClientID: "client1",
Name: "Roy",
}
if err := gormDB.Save(orders).Error; err != nil {
return
}
if err := gormDB.Session(&gorm.Session{FullSaveAssociations: true}).Model(&orders).Association("Albums").Append(albums); err != nil {
return
}
Full code could be found here:
答案2
得分: 0
在查看@giyuu提供的出色答案时,我找到了我正在寻找的解决方案。由于我之前没有保存该项,我需要使用GORM的Create
方法:
err = gormDB.Create(&test).Error
然后,当我想对这些值进行更新时,我使用Save
方法,并启用FullSaveAssociations
:
err = gormDB.Session(&gorm.Session{FullSaveAssociations: true}).Save(&test).Error
英文:
Came across the solution I was looking for while looking into the great answer @giyuu provided. Since I had not saved the item before, I needed to use GORM's Create
method:
err = gormDB.Create(&test).Error
Then, when I want to perform an update on any of these values, I use the Save
method, with FullSaveAssociations
enabled:
err = gormDB.Session(&gorm.Session{FullSaveAssociations: true}).Save(&test).Error
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论