【问题标题】:Update method does not update zero value更新方法不更新零值
【发布时间】:2021-01-27 12:19:38
【问题描述】:

原始问题

在 GORM 中使用 Update 方法时,新数据不会被保存。即我想将booltrue 设置为false,但即使在Update 方法之后它仍然是正确的。

在方法的描述中有一个警告:“WARNING when update with struct, GORM will not update fields that with zero value”

由于我使用结构进行更新并且falsebool 的零值,这似乎是预期的行为,但我看不出有任何理由这样做以及如何克服这个问题。

func UpdateData(c *fiber.Ctx) error {
    db := database.DBConn

    data := new([]entities.Data)

    if err := c.BodyParser(&data); err != nil {
        return err
    }

    db.Update(&data)
    return c.JSON(data)
}

解决方案总结

首先,正如建议的那样,我在实例化结构时省略了 new 关键字。然后,我使用辅助函数(来自here)将结构转换为映射,同时将 json 别名作为键:

// StructToMap Converts a struct to a map while maintaining the json alias as keys
func StructToMap(obj interface{}) (newMap map[string]interface{}, err error) {
    data, err := json.Marshal(obj)

    if err != nil {
        return
    }

    err = json.Unmarshal(data, &newMap) // Convert to a map
    return
}

然后我循环遍历数据切片中的每个元素,以便对其进行转换并一一更新:

func UpdateData(c *fiber.Ctx) error {
    db := database.DBConn

    data := []entities.Dard{}

    if err := c.BodyParser(&data); err != nil {
        return err
    }

    for _, record := range data {
        mappedData, _ := StructToMap(record)
        db.Model(&entities.Data{}).Update(mappedData)
    }

    return c.JSON(data)
}

*在这个例子中,错误处理明显减少了。

【问题讨论】:

  • 拒绝投票是故意匿名的。要求解释是不恰当的。
  • 反对票是不言自明的。根据定义,它们的意思是“这个问题没有显示任何研究成果;它不清楚或没有用”(将鼠标悬停在向下投票箭头上以查看此内容)。解释反对票的问题已经在 meta 上讨论了数千次。很无聊。
  • 为什么是这种行为的问题是要问 GORM 作者。如果将类型更改为指针不适合您,那么我没有想法。但我不是 GORM 用户,所以希望其他人能提供更好的东西。
  • "如何改进问题以获得更好的答案?" that 是寻求反馈的好方法。我没有任何建议。这个问题也只有一个小时的时间,所以我不希望得到很好的答案。
  • 尽量避免使用newdata*[]entities.Data 类型(new 是一个内置函数,看起来有点像:new(T) *T)。因此,您将**[]entities.Data 传递给BodyParserUpdate 函数。如果您的目标是创建一个新切片,请编写:data := []entities.Data{}data := make([]entities.Data, len, cap)。检查所有错误函数也可能返回

标签: go go-gorm go-fiber


【解决方案1】:

来自官方doc

注意 使用 struct 更新时,GORM 只会更新非零值 字段,您可能想使用地图来更新属性或使用选择 指定要更新的字段

所以也使用map[string]interface{} 来更新非零字段。示例:

db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})

由于您已经拥有结构,您可以将struct 转换为map[string]interface{} (See details about conversion) 然后更新。另一种方法是将字段类型更改为指针。

【讨论】:

  • 感谢您的回复。我试过这个,但我不确定如何将它与 data 变量一起使用,该变量保存传入的数据并且是一个结构切片(因此 new([]entities.Data))。使用map[string]interface{}{structs.Map(&data)} 不起作用。
  • 如果entities.Data 是您的模型,那么您需要将每个entities.Data 转换为map[string]interface{} 并调用Updates()
猜你喜欢
  • 2022-08-03
  • 2017-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-15
  • 1970-01-01
  • 2022-12-15
相关资源
最近更新 更多