在插入或更新表时,GORM错误违反了外键约束。

huangapple go评论88阅读模式
英文:

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

huangapple
  • 本文由 发表于 2022年8月20日 07:19:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/73423068.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定