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

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时,就会将该字段的值更新。

你可能感兴趣的:(gorm)