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