gorm 中的Updates Update, Save,Create , UpdateColumn 区别与联系
在 GORMGo 的 ORM 库中Updates、Update、Save、Create、UpdateColumn等方法都用于数据的写入或更新但它们的行为、触发的钩子Hooks、性能、适用场景有显著区别。以下是详细对比与联系:一、核心方法对比表方法用途是否触发 Hooks是否支持批量是否跳过零值是否需要主键备注Create插入新记录✅BeforeCreate,AfterCreate❌单条✅CreateInBatches批量❌插入所有字段❌自动生成 IDSave智能保存存在则更新否则插入✅ 全部 HooksBeforeCreate/Update,After...❌单条❌更新所有非零字段✅更新时需主键最“重”的操作慎用Update更新单个字段❌不触发BeforeUpdate❌✅可更新为零值✅或配合Where如Update(name, new)Updates更新多个字段⚠️仅当传 struct 时触发❌传map不触发✅配合Where✅struct 会跳过零值map 不会✅或配合Where最常用批量更新方式UpdateColumn强制更新字段包括零值❌✅❌强制更新含零值✅或配合Where绕过 GORM 安全机制二、逐个详解1.Createdb.Create(user)作用插入一条新记录。特点忽略主键自增或 UUID插入所有字段包括零值如,0触发BeforeCreate/AfterCreate不适用已有主键的记录可能报错或行为未定义2.Savedb.Save(user) // user.Id ! 0 → 更新user.Id 0 → 插入作用根据主键是否存在自动决定是INSERT还是UPDATE特点更新时会更新所有非零字段零值字段会被忽略⚠️ 常见坑触发完整 HooksBeforeCreate/BeforeUpdate等必须有主键才能更新。缺点性能差先查不一定但逻辑复杂零值字段无法更新比如想把name改成不行建议除非明确需要“智能保存”否则避免使用3.Update单字段db.Model(User{}).Where(id ?, 1).Update(name, new) // 或 db.Model(user).Update(name, new)作用更新单个字段特点不触发BeforeUpdate可更新为零值如Update(age, 0)有效必须配合Model()Where()或已有主键适用简单单字段更新4.Updates多字段(a)传map最常用db.Model(User{}).Where(id ?, 1).Updates(map[string]interface{}{ name: new, age: 0, })不触发 Hooks不会跳过零值age: 0会被更新高效适合批量更新(b) 传structdb.Model(User{}).Where(id ?, 1).Updates(User{Name: new, Age: 0})会触发BeforeUpdate/AfterUpdate会跳过零值字段Age: 0被忽略如果想更新零值需用指针或sql.NullInt64等关键区别Updates(map)vsUpdates(struct)行为完全不同5.UpdateColumndb.Model(User{}).Where(id ?, 1).UpdateColumn(name, )作用强制更新字段即使值为零值。不触发任何 Hooks绕过 GORM 的安全检查如字段不存在也会拼 SQL可能报错批量更新零值的唯一可靠方式⚠️ 危险慎用确保字段名正确三、钩子Hooks触发规则总结方法触发BeforeUpdate?Save(struct)✅Updates(struct{})✅Updates(map[...])❌Update(field, value)❌UpdateColumn(...)❌Create✅BeforeCreate核心原则只有通过struct 实例更新且 GORM 能识别为模型操作才会触发 Hooks在 GORM 中使用Updates时是否触发 Hooks如BeforeUpdate/AfterUpdate与是否开启事务无关不仅看Updates的参数类型还看Model()是否绑定了一个 struct 实例 ,传入的是map还是struct结论只要用map[string]interface{}调用Updates无论是否在事务中都不会触发任何 Hooks。这是 GORM 的设计行为事务不影响钩子的触发逻辑临时跳过钩子使用原生 SQL或Session 模式如果模型已经定义了钩子但某些特定操作想跳过钩子可以方法一使用Session(gorm.Session{SkipHooks: true})db.Session(gorm.Session{SkipHooks: true}).Create(user) db.Session(gorm.Session{SkipHooks: true}).Save(user) db.Session(gorm.Session{SkipHooks: true}).Delete(user)⚠️ 注意SkipHooks: true会跳过所有钩子包括BeforeCreate、AfterCreate等但不会跳过AfterFind因为AfterFind是在查询后自动调用的与写操作无关。方法二使用原生 SQL完全绕过 GORM 模型机制db.Exec(INSERT INTO users (name) VALUES (?), Alice)这种方式不会触发任何 GORM 钩子因为没有使用模型的 Create/Save 等方法四、如何选择场景推荐方法插入新记录Create更新部分字段含零值批量Updates(map) 手动设updated_at更新部分字段需触发BeforeUpdateUpdates(struct{})注意零值问题强制更新字段为零值UpdateColumn不确定是新增还是更新避免Save改用FirstOrCreate 显式更新单字段更新Update(field, value)五、最佳实践建议批量更新不要依赖 Hooks显式设置updated_at、updated_by避免使用Save除非你完全理解其零值行为Updates(map)是最安全高效的批量更新方式如果BeforeUpdate只是用来设时间戳直接在业务层赋值比依赖钩子更可靠想更新零值用map或UpdateColumn别用 struct
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2434048.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!