作者:matrix
发布时间:2024-10-21
分类:Golang
gorm中如果数据为结构体类型的零值时,不会触发零值更新。
比如当前有表结构体
type OrderTemplate struct {
ID int `gorm:"primaryKey;autoIncrement;column:id" json:"id"`
InputType int `gorm:"not null;default:1;column:input_type" json:"input_type"`
}
注意:
InputType类型为 int,设置了default为 1
当数据传入 0
,是 int 类型的默认零值0
,会认为你没有传入所以就用default值去填充。如果这里不配置default,系统也就不会写入数据。
解决方案
结构体字段使用非int
类型,如 sql.NullInt64
,*int
指针
简单点建议直接使用指针类型。使用sql.NullInt64类型传入时需要注意设置Valid为 true
sql.NullInt64{
Int64: 传入值,
Valid: true, // 表示这个传入值有效,即使它是 0
}
Valid: false 表示传入值无效,即写入默认 Null。
查询或者更新数据的时候也同样会遇到零值问题。
参考:
https://juejin.cn/post/7354940230301483017
作者:matrix
发布时间:2023-11-30
分类:Golang
使用gorm时,可能需要处理虚拟字段(不在数据库中实际存在的字段)的情况。可以使用结构体tag标签来支持
User结构体模型
type User struct {
ID uint `gorm:"primaryKey;not null"` // 主键ID
// 虚拟字段
Isvip int `gorm:"-;default:0"` // 是否vip 1是 0否
}
说明:
IsVip字段被标记为 gorm:"-"
,表示虚拟字段。GORM在进行数据库操作(如查询、插入、更新等)时,将不会考虑此字段。同时,可以使用default
标签为其指定默认值。
自定义获取器
自定义一个Get方法 例如,下面的GetIsVip方法会基于用户的VIP状态来返回相应的值:
func (u *User) GetIsVip() int {
if u.Vip != nil && u.Vip.IsActive == 1 {
return 1
}
return 0
}
应用获取器
在查询User对象时,GORM提供了 AfterFind
方法来自动执行特定逻辑。这在处理虚拟字段时很有用:
// 查询数据时自动赋值字段
func (u *User) AfterFind(tx *gorm.DB) (err error) {
if u.Vip == nil {
//TIPS:Association方法手动触发模型关联。如果使用Preload会再次查询User主表,不推荐
// tx.Preload("Vip").First(&u, u.ID) //不推荐
tx.Model(u).Association("Vip").Find(&u.Vip)
}
u.Isvip = u.GetIsVip() // 手动触发虚拟字段计算
return
}
说明:
首先检查VIP信息是否已加载。如果未加载,则使用Association方法手动触发加载。之后,我们使用前面定义的GetIsVip方法来计算并设置Isvip字段的值。
注意
使用AfterFind可能会覆盖Isvip字段的默认值(如default:0
)