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