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

问题背景

在使用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常量
    《gorm设置自定义数据类型字段的默认值》

  • 但是

  • 对于一些引用类型就不能直接设置默认值了,比如我想将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提供了我们解决方案,钩子官方文档链接
官方给出了如下说明
《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://blog.csdn.net/m0_38112165/article/details/119491518
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞