gorm设置自定义数据类型字段的默认值

gorm设置自定义数据类型字段的默认值,第1张

问题背景

在使用gorm时,往往默认的数据类型不满足我们的要求,需要使用一些自定义数据类型作为字段类型,并需要设置一些默认值,如下面例子。

定义一个Status数据类型和LocalTime数据类型,分别表示状态和时间,并实现Valuer和Scanner接口(不了解的话可以看gorm自定义数据类型官方文档)

说一下我自定义这两个数据类型的目的,想通过定义Status实现枚举,定义LocalTime实现时间的读取格式化

type Status int64
const (
	TaskStatusDisabled Status = 0 // 禁用
	TaskStatusFailure  Status = 1 // 失败
)
func (s Status) Value() (driver.Value, error) {
	return int64(s), nil
}
func (s *Status) Scan(value interface{}) error {
	v, ok := value.(int64)
	if ok {
		*s = Status(v)
		return nil
	}
	return errors.New("CustomizeDataTypeError")
}

type LocalTime time.Time

func (t LocalTime) Value() (driver.Value, error) {
	var zeroTime time.Time
	tlt := time.Time(t)
	if tlt.UnixNano() == zeroTime.UnixNano() {
		return nil, nil
	}
	return tlt, nil
}

func (t *LocalTime) Scan(v interface{}) error {
	if value, ok := v.(time.Time); ok {
		*t = LocalTime(value)
		return nil
	}
	return fmt.Errorf("can not convert %v to timestamp", v)
}
//实现时间格式化
func (t *LocalTime) MarshalJSON() ([]byte, error) {
	tTime := time.Time(*t)
	return []byte(fmt.Sprintf("\"%v\"", tTime.Format("2006-01-02 15:04:05"))), nil
}

在声明模型时使用这个Status和LocalTime,这里省略一些其他字段

type Task struct {
	...
	Status        Status       `json:status gorm:"default 0"`
	StartTime     *LocalTime   `json:"start_time" gorm:"notnull"` 
	...
}
正题来了!!(前面铺垫有点长…)

当我们设置默认值的时候,对于基本数据类型int、string、bool这些自定义数据类型可以在gorm:"default ##"后面直接设置对应的默认值就可以了,在插入数据时会系统会自动识别,并插入到DB,如上面定义的Status,配置gorm:"default 0"就可以实现

Debug时发现会将0识别为TaskStatusDisabled常量

但是

对于一些引用类型就不能直接设置默认值了,比如我想将LocalTime设置默认值

如我们想这么设置

	gorm: "default time.Parse('2006-01-02 15:04:05', '2999-12-31 23:59:59')"
或
   gorm: "default LocalTime(time.Parse('2006-01-02 15:04:05', '2999-12-31 23:59:59'))"
统统不起作用 解决方案

GORM提供了我们解决方案,钩子,官方文档链接
官方给出了如下说明

那我们可以通过在BeforeCreate方法中实现调用create方法前设置LocalTime的默认值

func (t *Task) BeforeCreate(tx *gorm.DB) error {
	endTime, _ := time.Parse("2006-01-02 15:04:05", "2999-12-31 23:59:59")
	et := LocalTime(endTime)
	t.EndTime = &et
	return nil
}

注意:虽然我没用tx *gorm.DB这个参数,但是这个参数也是必须要有的

说道这里,我们就可以发现这个钩子方法不仅仅可以设置默认值这么简单,可以调用tx.Update(),tx.Delete()等等方法,并且这些 *** 作在一个事务内,更可以在这里做自己想做的任何事情。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/990058.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存