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

相关推荐
2501_933670791 小时前
2026秋招数据分析岗备考路线:SQL、BI、项目与面试题拆解
数据库
我要见SA姐14 小时前
告别 Copilot?Codex 本地化部署指南
运维·数据库·机器学习·oracle·回归
xcLeigh4 小时前
聊聊国产化替换:好用数据迁移工具KDMS怎么帮咱们搞定评估难
数据库·sql·数据迁移·kes·kdms
Elastic 中国社区官方博客5 小时前
列式存储并不等同于列式数据库。Columnar 模式为 Elasticsearch 带来了什么
大数据·运维·数据库·elasticsearch·搜索引擎
参.商.5 小时前
【Day 53】76. 最小覆盖子串
leetcode·golang
我要见SA姐15 小时前
用 Claude Code 重构遗留系统:从评估到落地的完整实践指南
数据库·ide·vscode·oracle·编辑器
Nturmoils6 小时前
一份 KDMS 评估报告,怎样排出迁移先后顺序
数据库
这个DBA有点耶6 小时前
异构数据集成怎么做?5 种同步方案对比 + 金融级 CDC 实战解析
数据库·oracle·架构
独泪了无痕6 小时前
SQL函数实战:GREATEST与LEAST的技巧
数据库·sql·mysql
麻辣布丁7 小时前
MySQL篇面试题模拟
mysql