Gorm V2的使用感受和Save方法

Gorm V2的使用感受和Save方法

和v1对比
  • gorm-v2不支持多表情况下软硬删除的混合链式调用,否则会panic

  • gorm-v2的create如果在select后调用,会出现插入空值的情况,可以通过select().create或者用db.session来解决

    https://github.com/go-gorm/gorm/issues/4778
    
  • gorm-v2不需要subQuery了

  • gorm-v2没有newScope方法来获取表名了

给我目前最大的方便:
  • 可以进行批量插入了,且批量插入后能获取到对应的递增主键
Save的使用

由于业务需要用到不存在时插入,存在时更新的功能,于是就想到了Save方法。

使用save的前提

表中必须要指定主键。如果想要实现不存在插入,存在更新的功能,则传入参数有主键的情况一定要填上。

  • 如果save传的是结构体,那么如果这条记录不存在他会执行三条sql

    package dbtest
    
    var (
    	gdb *gorm.DB
    )
    
    func init() {
    	db, err := InitDBV2(false, false)
    	if err != nil {
    		log.Fatal("init db failed,err=" + err.Error())
    	}
    
    	gdb = db
    
    	if err = db.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;").AutoMigrate(&Recode{}); err != nil {
    		log.Error("create table error ", err)
    		return
    	}
    }
    
    type Recode struct {
    	FromWeb string `gorm:"primarykey"`
    	Author  string
    	Title   string
    	Time    string
    	LinkUrl string
    	Content string
    }
    
    func Test_save(t *testing.T) {
    	db := gdb.Debug()
    
    	r2 := Recode{
    		FromWeb: "10779",
    		Author:  "李四",
    		Title:   "Friday",
    	}
    
    	err := db.Save(&r2).Error
    	if err != nil {
    		t.Error("save failed,e=", err)
    		return
    	}
    }
    

    sql执行记录:

    2021/12/30 17:03:21 /root/code/test/db/db_test.go:104
    [0.756ms] [rows:0] UPDATE `recodes` SET `author`='李四',`title`='Friday',`time`='',`link_url`='',`content`='' WHERE `from_web` = '10779'
    
    2021/12/30 17:03:21 /root/code/test/db/db_test.go:104
    [0.565ms] [rows:0] SELECT * FROM `recodes` WHERE `from_web` = '10779' LIMIT 1
    
    2021/12/30 17:03:21 /root/code/test/db/db_test.go:104
    [6.697ms] [rows:1] INSERT INTO `recodes` (`from_web`,`author`,`title`,`time`,`link_url`,`content`) VALUES ('10779','李四','Friday','','','')
    --- PASS: Test_save (0.01s)
    
  • 如果用切片进行传参,则只会执行一条语句

    func Test_save(t *testing.T) {
    	db := gdb.Debug()
    
    	r2 := Recode{
    		FromWeb: "10779",
    		Author:  "李四",
    		Title:   "Friday",
    	}
    
    	var rs = []Recode{r2}
    	err := db.Save(&rs).Error
    	if err != nil {
    		t.Error("save failed,e=", err)
    		return
    	}
    }
    

    sql执行记录:

    2021/12/30 17:06:29 /root/code/test/db/db_test.go:104
    [0.627ms] [rows:0] INSERT INTO `recodes` (`from_web`,`author`,`title`,`time`,`link_url`,`content`) VALUES ('10779','李四','Friday','','','') ON DUPLICATE KEY UPDATE `author`=VALUES(`author`),`title`=VALUES(`title`),`time`=VALUES(`time`),`link_url`=VALUES(`link_url`),`content`=VALUES(`content`)
    

    因此建议如果是需要实现存在更新的场景,建议用切片传参

save 的选择性字段更新
  • 如果我只想每次只更新某几个字段,其他字段不更新,有没有什么方法。毕竟save是会将0值或者空串都会更新到数据库中的。于是可以用到Select方法:

    func Test_save(t *testing.T) {
    	db := gdb.Debug()
    
    	r2 := Recode{
    		FromWeb: "10779",
    		Author:  "李四",
    		Title:   "Friday",
    		LinkUrl: "www.baidu.com",
    	}
    
    	var rs = []Recode{r2}
    	//主键不要忘了填入select中
    	err := db.Select("from_web", "author", "title").Save(&rs).Error
    	if err != nil {
    		t.Error("save failed,e=", err)
    		return
    	}
    }
    

    可以看到sql的执行记录

    2021/12/30 17:12:23 /root/code/test/db/db_test.go:105
    [1.028ms] [rows:0] INSERT INTO `recodes` (`from_web`,`author`,`title`) VALUES ('10779','李四','Friday') ON DUPLICATE KEY UPDATE `author`=VALUES(`author`),`title`=VALUES(`title`)
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`Save` 和 `Update` 都是 GORM 操作数据库方法,但是它们之间有一些区别。 `Save` 方法用于插入一条新的记录或更新一条记录。如果传入的对象没有指定主键,那么 `Save` 方法会插入一条新纪录,否则会更新已有记录。如果该记录不存在,则插入一条新记录;如果该记录已存在,则更新该记录。如果你要更新某个字段的值,可以先查询出来,然后再修改,最后使用 `Save` 方法保存到数据库中。 例如: ```go // 新增一条记录 user := User{Name: "foo", Age: 18} db.Save(&user) // 更新记录 user.Age = 20 db.Save(&user) ``` `Update` 方法用于更新一条或多条记录。它接受一个 map 类型的参数,用于指定需要更新的字段和对应的值,然后根据指定的条件进行更新。如果没有指定条件,则会更新表中的所有记录。 例如: ```go // 更新一条记录 db.Model(&User{}).Where("id = ?", 1).Update("age", 20) // 更新多条记录 db.Model(&User{}).Where("age < ?", 18).Update("age", 18) ``` 需要注意的是,`Update` 方法只更新指定的字段,并且不会更新主键和自动更新的字段(如创建时间和更新时间等)。如果需要更新多个字段,可以传入一个 map 类型的参数。 综上所述,`Save` 和 `Update` 方法的区别在于,`Save` 方法既可以插入新记录,也可以更新已有记录,而 `Update` 方法只能更新已有记录,并且只能更新指定的字段。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值