Zhong__GORM零值创建/更新详解

时间:2022.11.25

环境:Windows Goland

目的:对比不同情况下(字段类型及tag定义的属性)零值创建的区别和零值更新的区别

说明:基于GORM 2.0 当前时间点是有效的 请以官方文档为主

作者:Zhong

目录

创建

1、有默认值

model

Create

2、无默认值

model

Create

更新

model

Update/UpdateColumn/Updates/UpdateColumns

Update/UpdateColumn

Updates/UpdateColumns


创建

1、有默认值

非指针 or 非实现了Scanner/Valuer接口的sql.NullXxx or 指针 or 实现了Scanner/Valuer接口的sql.NullXxx

model

定义结构体中对比的字段

SaleNum int            `json:"sale_num" gorm:"default:200"`  // 非指针 or 非实现了Scanner/Valuer接口的sql.NullXxx
ReadNum *int           `json:"read_num" gorm:"default:20"` //  指针
Comment sql.NullString `json:"comment" gorm:"column:comment;default:'暂无评论!'"`  // 实现了Scanner/Valuer接口的sql.NullXxx

Create

未传值时

全部使用默认值

article := Article{
   Title:  "石头记",
   Author: "曹雪芹",
}
db.Debug().Create(&article)
// INSERT INTO `article` (`created_at`,`updated_at`,`deleted_at`,`title`,`author`,`sale_num`,`read_num`,`comment`) 
// VALUES ('2022-11-24 20:17:42.16','2022-11-24 20:17:42.16',NULL,'石头记','曹雪芹',200,20,'暂无评论!')

传值时

非零值使用传递的值

零值指针类型和sql.NullXxx类型可传入零值

其它类型如int忽略零值而使用默认值

read_num := 222
article := Article{
   Title:   "石头记",
   Author:  "曹雪芹",
   SaleNum: 111,
   ReadNum: &read_num,
   Comment: sql.NullString{"好", true},
}
db.Debug().Create(&article)
// INSERT INTO `article` (`created_at`,`updated_at`,`deleted_at`,`title`,`author`,`sale_num`,`read_num`,`comment`) 
// VALUES ('2022-11-25 01:22:25.246','2022-11-25 01:22:25.246',NULL,'石头记','曹雪芹',111,222,'好')

article := Article{
   Title:   "石头记",
   Author:  "曹雪芹",
   SaleNum: 0,
   ReadNum: new(int),
   Comment: sql.NullString{"", true},
}
db.Debug().Create(&article)
// INSERT INTO `article` (`created_at`,`updated_at`,`deleted_at`,`title`,`author`,`sale_num`,`read_num`,`comment`) 
// VALUES ('2022-11-25 01:26:33.933','2022-11-25 01:26:33.933',NULL,'石头记','曹雪芹',200,0,'')

2、无默认值

非指针 or 非实现了Scanner/Valuer接口的sql.NullXxx or 指针 or 实现了Scanner/Valuer接口的sql.NullXxx

model

定义结构体中对比的字段

SaleNum int            `json:"sale_num"`
ReadNum *int           `json:"read_num"`
Comment sql.NullString `json:"comment"`

Create

未传值时

指针类型如 *int 和 sql.NullXxx类型如 sql.NullString 使用空值 Null

其它类型使用零值如 int 类型零值 0

article := Article{
   Title:  "石头记",
   Author: "曹雪芹",
}
db.Debug().Create(&article)
// INSERT INTO `article` (`created_at`,`updated_at`,`deleted_at`,`title`,`author`,`sale_num`,`read_num`,`comment`) 
// VALUES ('2022-11-25 01:39:21.473','2022-11-25 01:39:21.473',NULL,'石头记','曹雪芹',0,NULL,NULL)

传值时

参数非零值使用传递的值

参数零值指针类型和 sql.NullXxx 类型以及其它类型如int使用零值

即 只要传了字段值  就使用传递的值

read_num := 200
article := Article{
   Title:   "石头记",
   Author:  "曹雪芹",
   SaleNum: 100,
   ReadNum: &read_num,
   Comment: sql.NullString{"好好", true},
}
db.Debug().Create(&article)
// INSERT INTO `article` (`created_at`,`updated_at`,`deleted_at`,`title`,`author`,`sale_num`,`read_num`,`comment`) 
// VALUES ('2022-11-25 01:38:17.277','2022-11-25 01:38:17.277',NULL,'石头记','曹雪芹',100,200,'好好')

article := Article{
   Title:   "石头记",
   Author:  "曹雪芹",
   SaleNum: 0,
   ReadNum: new(int),
   Comment: sql.NullString{"", true},
}
db.Debug().Create(&article)
// INSERT INTO `article` (`created_at`,`updated_at`,`deleted_at`,`title`,`author`,`sale_num`,`read_num`,`comment`) 
// VALUES ('2022-11-25 01:34:53.4','2022-11-25 01:34:53.4',NULL,'石头记','曹雪芹',0,0,'')

Note

此外 gorm支持使用map[string]interface{} 和 []map[string]interface{}{}创建数据 当使用map创建时 钩子函数不会被调用 关联关系不会被保存 主键值不会被回填

db.Model(&Article{}).Debug().Create(map[string]interface{}{
   "Title": "红楼梦", "Author": "曹雪芹",
})
// INSERT INTO `article` (`author`,`title`) VALUES ('曹雪芹','红楼梦')

db.Model(&Article{}).Debug().Create([]map[string]interface{}{
   {"Title": "水浒传", "Author": "施耐庵"},
   {"Title": "西游记", "Author": "吴承恩"},
})
// INSERT INTO `article` (`author`,`title`) VALUES ('施耐庵','水浒传'),('吴承恩','西游记')

更新

Update/UpdateColumn单列更新使用Update(column string, value interface{})都能更新零值

如果想要多列更新(Updates/UpdateColumns)零值如字符串类型 可使用以下3种方案

  • Info string 使用map/struct(配合Select指定字段 "info")
  • Info *string 使用map/struct(Info: new(string))
  • Info sql.NullString 使用map/struct(Info: sql.NullString{"", true})

详细使用如下举例

model

定义结构体中对比的字段

SaleNum int            `json:"sale_num" gorm:"default:200"`  // 非指针 or 非实现了Scanner/Valuer接口的sql.NullXxx
ReadNum *int           `json:"read_num" gorm:"default:20"` //  指针
Comment sql.NullString `json:"comment" gorm:"column:comment;default:'暂无评论!'"`  // 实现了Scanner/Valuer接口的sql.NullXxx

Update/UpdateColumn/Updates/UpdateColumns

Update/UpdateColumn

单列更新零值/非零值(非零值其实不涉及问题) 均能更新指定值

// Update(UpdateColumn同理) 零值可以更新到表
db.Model(&Article{}).Debug().Where("title = ?", "石头记").Update("sale_num", 0)
db.Model(&Article{}).Debug().Where("title = ?", "石头记").Update("read_num", 0)
db.Model(&Article{}).Debug().Where("title = ?", "石头记").Update("comment", "")

Updates/UpdateColumns

多列更新零值/非零值(非零值其实不涉及问题)

map可以更新指定值(零值也生效)

struct零值更新只对指针和实现了Scanner/Valuer接口的类型如sql.NullString等sql.NullXxx类型有效 其它类型如整形类型 int 则会忽略零值 0

如果要使此种类型零值更新 可以使用Select指定要更新的值

// Updates/UpdateColumns3种情况下的零值变化
// 1、Updates(UpdateColumns同理) with map 更新零值
db.Model(&Article{}).Debug().Where("title = ?", "石头记").Updates(map[string]interface{}{
   "sale_num": 0,
   "read_num": 0,
   "comment":  "",
})
// UPDATE `article` SET `comment`='',`read_num`=0,`sale_num`=0,`updated_at`='2022-11-24 23:40:32.434' 
// WHERE title = '石头记' AND `article`.`deleted_at` IS NULL

// 2、Updates(UpdateColumns同理) with struct 不更新零值
db.Model(&Article{}).Debug().Where("title = ?", "石头记").Updates(&Article{
   SaleNum: 0,
   ReadNum: new(int),
   Comment: sql.NullString{"", true},
})
// UPDATE `article` SET `updated_at`='2022-11-24 23:28:37.34',`read_num`=0,`comment`='' 
// WHERE title = '石头记' AND `article`.`deleted_at` IS NULL

// 3、Updates(UpdateColumns同理) with struct and Select condition 更新零值
db.Model(&Article{}).Debug().Where("title = ?", "石头记").Select("sale_num", "read_num", "comment").Updates(&Article{
   SaleNum: 0,
   ReadNum: new(int),
   Comment: sql.NullString{"", true},
})
// UPDATE `article` SET `updated_at`='2022-11-25 00:38:27.089',`sale_num`=0,`read_num`=0,`comment`='' 
// WHERE title = '石头记' AND `article`.`deleted_at` IS NULL

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我变了_我没变

随意 。。。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值