提问帖,为什么gorm 在BeforeUpdate 中使用tx.Omit 不生效

197 阅读2分钟

为什么使用gorm 在BeforeUpdate 中使用tx.Omit 不生效 具体代码:

func (m *ShopSystemMerchant) BeforeUpdate(tx *gorm.DB) (err error) {
   m.UpdateAt = utils.PtrTime(time.Now())
   if m.ExpireTime.IsZero() {
      fmt.Println("Expire time is zero")
      tx = tx.Statement.Omit("expire_time")
   }
   return nil
}

实际控制台打印出了 Expire time is zero 且,mysql 也提示expire_time不能为空;(设置了该字段不能为空)

查看文档并没有找到什么

遂去问gpt

gpt回答内容:

当你的 GORM 钩子中的 `tx.Omit("expire_time")` 没有如预期般生效时,可以考虑以下几个方面的排查:

1.  **日志调试:** 确保启用了详细的 GORM 日志,查看更新语句的生成是否符合预期。你可以通过设置 `db.LogMode(logger.Info)` 来启用详细的日志输出。检查控制台或日志文件,看看生成的 SQL 语句是否正确。
1.  **数据库字段映射:** 确保数据库表中的字段与 GORM 模型的字段映射正确。字段名称和数据类型都应该一致。有时数据库字段命名规范或大小写敏感性可能导致问题。
1.  **查看 Update 操作是否执行成功:** 在 `tx.Omit("expire_time")` 之后,检查是否有其他操作或错误导致更新操作未成功。可以使用 GORM 提供的错误返回值检查是否有错误发生。
1.  **尝试其他方法:** 如果问题仍然存在,尝试使用其他方式来排除 `expire_time` 字段,例如使用 `tx.Statement.Omit("expire_time")` 或者 `tx.Statement.ColumnExpr("expire_time = expire_time")`。

下面是一个示例,演示如何使用 `tx.Statement.Omit`
func (m *ShopSystemMerchant) BeforeUpdate(tx *gorm.DB) (err error) { 
    m.UpdateAt = utils.PtrTime(time.Now())
    if m.ExpireTime.IsZero() { fmt.Println("Expire time is zero")
        tx.Statement.Omit("expire_time") 
    } 
    return nil 
}

修改代码为tx.Statement.Omit("expire_time") ,测试可以生效了,但是看文档内容,没有说还能这么用啊; 关键这么用是什么意思呢?有没有其他的影响,请各位解疑!

感谢!!!

文档内容

1706002072500.png