go语言,ent库与gorm库,插入一条null值的time数据

情景介绍

使用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

参考资源

问如何告诉gorm将缺少的time.Time字段保存为NULL,而不是'0000-00-00'?
ent官方FAQ

相关推荐
爬山算法4 分钟前
MongoDB(80)如何在MongoDB中使用多文档事务?
数据库·python·mongodb
APguantou11 分钟前
NCRE-三级数据库技术-第2章-需求分析
数据库·需求分析
寂夜了无痕1 小时前
MySQL 主从延迟全链路根因诊断与破局法则
数据库·mysql·mysql主从延迟
爱丽_1 小时前
分页为什么越翻越慢:offset 陷阱、seek 分页与索引排序优化
数据库·mysql
APguantou1 小时前
NCRE-三级数据库技术-第12章-备份与数据库恢复
数据库·sqlserver
Bat U1 小时前
MySQL数据库|表设计+新增+分组查询
数据库·mysql
麦聪聊数据1 小时前
企业数据流通与敏捷API交付实战(五):异构数据跨库联邦与零代码发布
数据库·sql·低代码·restful
Elastic 中国社区官方博客1 小时前
当 TSDS 遇到 ILM:设计不会拒绝延迟数据的时间序列数据流
大数据·运维·数据库·elasticsearch·搜索引擎·logstash
qing222222221 小时前
Linux中修改mysql数据表
linux·运维·mysql
Omics Pro1 小时前
虚拟细胞:开启HIV/AIDS治疗新纪元的关键?
大数据·数据库·人工智能·深度学习·算法·机器学习·计算机视觉