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

相关推荐
静听山水1 分钟前
mysql语句执行过程
数据库·mysql
虽千万人 吾往矣20 分钟前
golang gorm
开发语言·数据库·后端·tcp/ip·golang
Q_w774239 分钟前
一个真实可用的登录界面!
javascript·mysql·php·html5·网站登录
mariokkm43 分钟前
Django一分钟:在Django中怎么存储树形结构的数据,DRF校验递归嵌套模型的替代方案
数据库·django·sqlite
Wang's Blog2 小时前
Redis: 集群环境搭建,集群状态检查,分析主从日志,查看集群信息
数据库·redis
容器( ु⁎ᴗ_ᴗ⁎)ु.。oO2 小时前
MySQL事务
数据库·mysql
数据龙傲天3 小时前
1688商品API接口:电商数据自动化的新引擎
java·大数据·sql·mysql
engineer-gxd4 小时前
MySQL 表的操作
mysql
cyt涛4 小时前
MyBatis 学习总结
数据库·sql·学习·mysql·mybatis·jdbc·lombok
Rookie也要加油4 小时前
01_SQLite
数据库·sqlite