【Gorm】用save更新软删除过的字段踩坑记录

934 阅读1分钟

问题

客户列表写好之后,在测试更新的时候遇到了一个问题

对一个客户详情没有进行改动之后点击保存(更新)会报Duplicate entry 'xxxx' for key 'PRIMARY'"的错误。

但是Save相当于FirstOrCreate,因为我已经查询出了要更新的记录,并且有id,按理说这时候的Save等同于Update操作,为什么会报这种错呢?

看了Save的实现:

// Save update value in database, if the value doesn't have primary key, will insert it
func (s *DB) Save(value interface{}) *DB {
   scope := s.NewScope(value)
   if !scope.PrimaryKeyZero() {
      newDB := scope.callCallbacks(s.parent.callbacks.updates).db
      if newDB.Error == nil && newDB.RowsAffected == 0 {
         return s.New().FirstOrCreate(value)
      }
      return newDB
   }
   return scope.callCallbacks(s.parent.callbacks.creates).db
}

注意这里的if newDB.Error == nil && newDB.RowsAffected == 0,在主键不为0的时候,会先进行更新的操作,如果更新返回的rowsAffected 为0才会去执行FirstOrCreate。 没有任何改动去更新的时候,rowsAffected为0,这时候进入FirstOrCreate,而FirstOrCreate的where语句中有deleted_at IS NULL,但是这里我的记录是已经被软删除过的,所以会创建新的记录,因此在这里就有主键冲突。

反之,如果有改动的时候因为rowsAffected不为0,那么就会正常的执行update

解决办法

  • 不用Save,改用Update
  • 返回列表中不显示已经被删除过的用户