情景介绍
使用go语言,我需要保存xxxTime的字段至数据库中,这个字段可能为空,也可能是一段时间。我采取的是统一先赋值为空,若有需要,则再进行插入(需要根据另一个字段判断是否插入)
在我的数据库中,使用的是DATETIME类型字段,代码中,采用的是time.Time 类型(这里有几个修改)。
使用Gorm库的实现
将xxxTime字段设置为sql.NullTime类型
在存储前,设置时
            
            
              go
              
              
            
          
          	res := Result{
        ...省略...
	xxxTime: sql.NullTime{
			Time:  time.Time{},
			Valid: false,
		},
        ...省略...
    }
        在存储时
            
            
              go
              
              
            
          
          	if err := db.Table(Table1).Create(&res).Error; err != nil {
	log.Error("保存数据时出错:", err)
		return -1, err
	}
        即可保存一条null值

之后采用进行插入即可
            
            
              go
              
              
            
          
          	currentTime := time.Now()
	tmpTime := currentTime.Add(time.Duration(msgInfo.RetryIntervalMinutes) * time.Minute)
	xxxTime = tmpTime.Format("2006-01-02 15:04:05")       
    err := db.Table(Table1).Where("id = ?", id).Update(xxxTime, xxxTime).Error
        使用ENT库
使用ent库进行同样的操作,但是遇到了很多问题。
使用sql.NullTime格式
遭遇失败
首先是采取同样的方式:同样是设置格式为sql.NullTime(此处导入的是import "entgo.io/ent/dialect/sql",先前版本导入的是import "database/sql")
同样赋值操作是
            
            
              go
              
              
            
          
          	res := Result{
        xxxTime: sql.NullTime{
			Time:  time.Time{},
			Valid: false,
		}}
        保存操作为
            
            
              go
              
              
            
          
          		SetxxxTime(res.xxxTime)
        但是会在这句报错,报错内容为:无法将 'res.xxxTime' (类型 sql.NullTime) 用作类型 time.Time
如果换为"database/sql"中的nulltime,依旧报错。无法将 'res.xxxTime' (类型 sql.NullTime) 用作类型 time.Time。
毕竟生成的代码中,所接受的传参就是t time.Time格式而不是其他,故显然是无法sql.nullTime的的...
            
            
              go
              
              
            
          
          // SetxxxTime sets the "xxx" field.
func (dlsc *DeadLetterServerCreate) SetxxxTime(t time.Time) *DeadLetterServerCreate {
	dlsc.mutation.SetxxxTime(t)
	return dlsc
}
// SetNillablexxxTime sets the "xxx" field if the given value is not nil.
func (dlsc *DeadLetterServerCreate) SetNillablexxxTime(t *time.Time) *DeadLetterServerCreate {
	if t != nil {
		dlsc.SetxxxTime(*t)
	}
	return dlsc
}
        为什么gorm可以?
而为什么gorm中可以呢?
            
            
              go
              
              
            
          
          func (db *DB) Create(value interface{}) (tx *DB) {
	if db.CreateBatchSize > 0 {
		return db.CreateInBatches(value, db.CreateBatchSize)
	}
	tx = db.getInstance()
	tx.Statement.Dest = value
	return tx.callbacks.Create().Execute(tx)
}
        翻看gorm中Create的源码,发现他所接受的是interface{}接口,因此就可以了...
保存为指针类型
参考此篇文章,里面是gorm库下的解决方啊,他提供了两种方法------sql.nullTime和保存为指针。因此照猫画虎,尝试第二种方案------保存为指针。
修改相关代码如下:
	xxx *time.Time `db:"xxx"`
	res := Result{
       		xxx: nil,
		}
        报错同上:毕竟是指定死类型的不是接口,所以肯定不对...
无法将 'res.xxx' (类型 *time.Time) 用作类型 time.Time
采用自动生成的 SetNillablexxx方法
在上面查看生成代码中,发现了这样一个函数
            
            
              go
              
              
            
          
          // SetNillablexxx sets the "xxx" field if the given value is not nil.
func (dlsc *DeadLetterServerCreate) SetNillablexxx(t *time.Time) *DeadLetterServerCreate {
	if t != nil {
		dlsc.Setxxx(*t)
	}
	return dlsc
}
        他看起来就是实现了这样的功能,因此我们修改调用为这个。
            
            
              go
              
              
            
          
          SetNillableNextRetryTime(res.NextRetryTime).
        运行后发现,可以正常保存。

完结,撒花!!
新的问题
这样可以保存NULL了,但我想真正保存时间时候,却无法保存了...
            
            
              go
              
              
            
          
          	testTime := time.Now()
	mh.Db.MainDB.UpdateOneID(id).SetNillableNextRetryTime(&testTime)
        前面一直以为是格式化问题,修改了半天还是不行。。
后来我直接用这样的语句,结果都存不进去东西。
遂修改,增加错误输出:
            
            
              go
              
              
            
          
          	mh.Db.MainDB.UpdateOneID(id).SetNillableNextRetryTime(&nextRetryTime)
        结果错误是nil,然后这时候,他就神奇的,成功了...!!
迷惑ing