关于gorm:gorm源码-自动更新时间字段

11次阅读

共计 2636 个字符,预计需要花费 7 分钟才能阅读完成。

gorm 反对对 model 中的工夫字段进行默认操作:

  • CreatedAt:创立工夫
  • UpdatedAt:更新工夫
  • DeletedAt: 删除工夫

也就是说,若 model 中含有上述字段,在 CRUD 操作时,gorm 会自动更新上述的工夫字段的值为 now()。

删除的时候

删除的 callbacks:

// github.com/jinzhu/gorm/callback_delete.go
// Define callbacks for deleting
func init() {
   ......
   DefaultCallback.Delete().Register("gorm:delete", deleteCallback)
   ......
}

在 deleteCallback 中,依据 model 中是否有 DeletedAt 字段,决定是执行 update 还是 delete:

// deleteCallback used to delete data from database or set deleted_at to current time (when using with soft delete)
func deleteCallback(scope *Scope) {if !scope.HasError() {
      var extraOption string
      if str, ok := scope.Get("gorm:delete_option"); ok {extraOption = fmt.Sprint(str)
      }
      // 查找 DeletedAt 字段
      deletedAtField, hasDeletedAtField := scope.FieldByName("DeletedAt")

      if !scope.Search.Unscoped && hasDeletedAtField {    //model struct 中有 DeletedAt 字段
         scope.Raw(fmt.Sprintf(
            "UPDATE %v SET %v=%v%v%v",                    // 执行 update-sql
            scope.QuotedTableName(),
            scope.Quote(deletedAtField.DBName),           // 将 UpdateAt 对应的 db 字段更新为 now()
            scope.AddToVars(scope.db.nowFunc()),
            addExtraSpaceIfExist(scope.CombinedConditionSql()),
            addExtraSpaceIfExist(extraOption),
         )).Exec()} else {
         scope.Raw(fmt.Sprintf(
            "DELETE FROM %v%v%v",                    //model struct 中没有 DeletedAt 字段,执行 delete-sql
            scope.QuotedTableName(),
            addExtraSpaceIfExist(scope.CombinedConditionSql()),
            addExtraSpaceIfExist(extraOption),
         )).Exec()}
   }
}

插入的时候

插入的 callbacks:

// github.com/jinzhu/gorm/callback_create.go
// Define callbacks for creating
func init() {
   ......
   DefaultCallback.Create().Register("gorm:update_time_stamp", updateTimeStampForCreateCallback)
   DefaultCallback.Create().Register("gorm:create", createCallback)
   ......
}

在 updateTimeStampForCreateCallback 这个 callback,进行了工夫字段的解决:

  • 查找 value 中是否有 CreatedAt 和 UpdatedAt 字段;
  • 若有,将其值设置为 now();
// updateTimeStampForCreateCallback will set `CreatedAt`, `UpdatedAt` when creating
func updateTimeStampForCreateCallback(scope *Scope) {if !scope.HasError() {now := scope.db.nowFunc()

      if createdAtField, ok := scope.FieldByName("CreatedAt"); ok {
         if createdAtField.IsBlank {createdAtField.Set(now)
         }
      }

      if updatedAtField, ok := scope.FieldByName("UpdatedAt"); ok {
         if updatedAtField.IsBlank {updatedAtField.Set(now)
         }
      }
   }
}

前面在 createCallback 执行 insert-sql 时,就会将该字段的值插入进去。

更新的时候

更新的 callbacks:

// github.com/jinzhu/gorm/callback_update.go
// Define callbacks for updating
func init() {
   ......
   DefaultCallback.Update().Register("gorm:update_time_stamp", updateTimeStampForUpdateCallback)
   DefaultCallback.Update().Register("gorm:update", updateCallback)
   ......
}

在 updateTimeStampForUpdateCallback 这个 callback,进行了工夫字段的解决:将 model-struct 中 UpdatedAt 这个字段的值,赋值为 now()。

// updateTimeStampForUpdateCallback will set `UpdatedAt` when updating
func updateTimeStampForUpdateCallback(scope *Scope) {if _, ok := scope.Get("gorm:update_column"); !ok {scope.SetColumn("UpdatedAt", scope.db.nowFunc())
   }
}

前面在 updateCallback 执行 update-sql 时,就会将该字段的值更新。

正文完
 0