更新HasMany关联失败Gorm

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

Update HasMany Association failing Gorm

问题

当我尝试使用获取的数据更新Shoppinglist结构时,出现了"there is no unique or exclusion constraint matching the ON CONFLICT specification (SQLSTATE 42P10)"错误。

这是我的结构体:

type Shoppinglist struct {
	Model

	ID           int            `gorm:"primaryKey" json:"id"`
	Title        string         `json:"title"`
	Items        []Item         `json:"items" gorm:"foreignKey:ParentListID;references:ID;"`
	Owner        string         `json:"owner"`
	Participants pq.StringArray `gorm:"type:text[]" json:"participants"`
}

type Item struct {
	Model

	ParentListID int    `gorm:"primaryKey" json:"parentListId"`
	Title        string `json:"title"`
	Position     int    `json:"position"`
	Bought       bool   `json:"bought"`
}

这是我在尝试编辑列表时执行的代码:

func EditList(id int, data map[string]interface{}) error {
	//https://github.com/go-gorm/gorm/issues/3487

	shoppinglist := Shoppinglist{
		ID:           data["id"].(int),
		Title:        data["title"].(string),
		Items:        data["items"].([]Item),
		Owner:        data["owner"].(string),
		Participants: data["participants"].([]string),
	}

	if err := db.Session(&gorm.Session{FullSaveAssociations: true}).Where("id = ?", id).Updates(&shoppinglist).Error; err != nil {
		return err
	}

	return nil
}

这是我执行EditList并设置所有值传递给map的地方:

type Shoppinglist struct {
	ID           int
	Title        string
	Items        []models.Item
	Owner        string
	Participants []string
	PageNum      int
	PageSize     int
}

func (s *Shoppinglist) Edit() error {
	shoppinglist := map[string]interface{}{
		"id":           s.ID,
		"title":        s.Title,
		"items":        s.Items,
		"owner":        s.Owner,
		"participants": s.Participants,
	}

	return models.EditList(s.ID, shoppinglist)
}

之前我只使用了[]string而不是[]Item,那时一切都更新得很好。现在除了[]Item之外,其他都更新了。

这是执行的SQL查询:

UPDATE "shoppinglists" SET "modified_on"=1628251977096,"title"='kjhdsfgnb',"owner"='janburzinski1@gmail.com',"participants"='{}' WHERE id = 517687 AND "id" = 517687

INSERT INTO "items" ("created_on","modified_on","deleted_at","title","position","bought","parent_list_id") VALUES (1628251977,1628251977116,NULL,'dfkjhgndfjkg',1,false,517687),(1628251977,1628251977116,NULL,'dfgh123',2,true,517687) ON CONFLICT ("parent_list_id") DO UPDATE SET "created_on"="excluded"."created_on","modified_on"="excluded"."modified_on","deleted_at"="excluded"."deleted_at","title"="excluded"."title","position"="excluded"."position","bought"="excluded"."bought" RETURNING "parent_list_id"

我真的想知道如何在Gorm中更新关系,或者为什么这不起作用,因为我已经在Github和Stackoverflow上查看了所有关联问题,但没有找到适合我的答案。

英文:

When I try to update the Shoppinglist struct with the data I get an "there is no unique or exclusion constraint matching the ON CONFLICT specification (SQLSTATE 42P10)" Error

These are my Structs

type Shoppinglist struct {
	Model

	ID           int            `gorm:"primaryKey" json:"id"`
	Title        string         `json:"title"`
	Items        []Item         `json:"items" gorm:"foreignKey:ParentListID;references:ID;"`
	Owner        string         `json:"owner"`
	Participants pq.StringArray `gorm:"type:text[]" json:"participants"`
}

type Item struct {
	Model

	ParentListID int    `gorm:"primaryKey" json:"parentListId"`
	Title        string `json:"title"`
	Position     int    `json:"position"`
	Bought       bool   `json:"bought"`
}

And this is the Code I execute when trying to edit a list

func EditList(id int, data map[string]interface{}) error {
	//https://github.com/go-gorm/gorm/issues/3487

	shoppinglist := Shoppinglist{
		ID:           data["id"].(int),
		Title:        data["title"].(string),
		Items:        data["items"].([]Item),
		Owner:        data["owner"].(string),
		Participants: data["participants"].([]string),
	}

	if err := db.Session(&gorm.Session{FullSaveAssociations: true}).Where("id = ?", id).Updates(&shoppinglist).Error; err != nil {
		return err
	}

	return nil
}

This is where I execute the EditList and where I set all the values to pass nito the map:

type Shoppinglist struct {
	ID           int
	Title        string
	Items        []models.Item
	Owner        string
	Participants []string
	PageNum      int
	PageSize     int
}

func (s *Shoppinglist) Edit() error {
	shoppinglist := map[string]interface{}{
		"id":           s.ID,
		"title":        s.Title,
		"items":        s.Items,
		"owner":        s.Owner,
		"participants": s.Participants,
	}

	return models.EditList(s.ID, shoppinglist)
}

Before I was just using a []string instead of []Item and that was working perfectly. Now everything updates except for the []Item

These are the SQL Queries executed:

UPDATE "shoppinglists" SET "modified_on"=1628251977096,"title"='kjhdsfgnb',"owner"='janburzinski1@gmail.com',"participants"='{}' WHERE id = 517687 AND "id" = 517687

INSERT INTO "items" ("created_on","modified_on","deleted_at","title","position","bought","parent_list_id") VALUES (1628251977,1628251977116,NULL,'dfkjhgndfjkg',1,false,517687),(1628251977,1628251977116,NULL,'dfgh123',2,true,517687) ON CONFLICT ("parent_list_id") DO UPDATE SET "created_on"="excluded"."created_on","modified_on"="excluded"."modified_on","deleted_at"="excluded"."deleted_at","title"="excluded"."title","position"="excluded"."position","bought"="excluded"."bought" RETURNING "parent_list_id"

I would really like to know how to Update a Relation in Gorm or why this isn't working because I've been looking through all the Association Issues on Github and Stackoverflow and didn't find a answer that worked for me.

答案1

得分: 0

我在这里看到的第一个问题是,你的Item没有ID,而是使用ParentListID作为主键。这意味着你每个父级只能有一个Item,这违背了使用数组的目的。

为Item创建一个ID字段(用作主键),如果你的方法仍然存在问题,请更新问题。

PS:本来应该在评论中留下这个建议,但是无法评论。

英文:

The first problem I see here is that your Item has no ID but uses the ParentListID as primary key. That means you can only have one Item for each parent which defeats the purpose of having an array.

Create an ID field (used as primary key) for items and if there's still issues with your approach, please update the question.

PS: would have left this in a comment, but can't.

答案2

得分: 0

我只需要在[]Item后面添加*,修复primaryKey的问题并移除引用即可。

type Shoppinglist struct {
    Model

    ID           int            `gorm:"primaryKey" json:"id"`
    Title        string         `json:"title"`
    Items        []*Item        `json:"items" gorm:"foreignKey:ParentListID;"`
    Owner        string         `json:"owner"`
    Participants pq.StringArray `gorm:"type:text[]" json:"participants"`
}

type Item struct {
    Model

    ID           int    `gorm:"primaryKey" json:"id"`
    ParentListID int    `json:"parentListId"`
    ItemID       int    `json:"itemId"`
    Title        string `json:"title"`
    Position     int    `json:"position"`
    Bought       bool   `json:"bought" gorm:"default:false"`
}
英文:

I just needed to add the * to the []Item and fix the problem with the primarykey and remove the reference.

type Shoppinglist struct {
	Model

	ID           int            `gorm:"primaryKey" json:"id"`
	Title        string         `json:"title"`
	Items        []*Item        `json:"items" gorm:"foreignKey:ParentListID;"`
	Owner        string         `json:"owner"`
	Participants pq.StringArray `gorm:"type:text[]" json:"participants"`
}

type Item struct {
	Model

	ID           int    `gorm:"primaryKey" json:"id"`
	ParentListID int    `json:"parentListId"`
	ItemID       int    `json:"itemId"`
	Title        string `json:"title"`
	Position     int    `json:"position"`
	Bought       bool   `json:"bought" gorm:"default:false"`
}

huangapple
  • 本文由 发表于 2021年8月8日 16:39:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/68699122.html
匿名

发表评论

匿名网友

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

确定