GORM模型更新

GORM模型更新

一、更新所有字段

Save()默认会更新该对象的所有字段,即使你没有赋值。

package main

import (
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type UsersUpdate struct {
	gorm.Model
	//Name *string `gorm:"type:varchar(100);default:RandySun;comment:姓名"`
	Name string `gorm:"type:varchar(100);default:RandySun;comment:姓名"`
	Age  int64
	// 设置默认值
	Active bool
}

func main() {
	dsn := "root:@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic(err)
	}
	// 迁移表创建对应关系
	db.AutoMigrate(&UsersUpdate{})

	// 添加数据
	db.Debug().Create(&UsersUpdate{Name: "bary", Age: 18})
	db.Debug().Create(&UsersUpdate{Name: "RandySun", Age: 18})
	db.Debug().Create(&UsersUpdate{Name: "Jack", Age: 18})
	db.Debug().Create(&UsersUpdate{Name: "", Age: 19}) // 添加记录name默认为Null

	// 查询
	var user UsersSelect
	db.Debug().First(&user)
	fmt.Printf("%#v", user)
    
	// 更新
	user.Name = "xiaoSun"
	user.Age = 18
	// 保存 save默认更新所有字段
    // UPDATE `users_updates` SET `created_at`='2021-11-23 22:24:20.984',`updated_at`='2021-11-23 22:27:27.243',`deleted_at`=NULL,`name`='xiaoSun',`age`=18,`active`=false WHERE `id` = 1
	db.Debug().Save(&user)


}

UPDATEusers_updatesSETcreated_at='2021-11-23 22:24:20.984',updated_at='2021-11-23 22:27:27.243',deleted_at=NULL,name='xiaoSun',age=18,active=false WHERE id = 1

image-20211123222837794

image-20211123222813916

二、更新修改字段

如果你只希望更新指定字段,可以使用Update或者Updates

2.1更新指定字段

// 根据给定的条件更新单个属性
UPDATE `users_updates` SET `name`='Randy',`updated_at`='2021-11-23 22:52:04.414' WHERE `id` = 1
db.Debug().Model(&user).Update("name","Randy")

image-20211123225215767

image-20211123225304164

2.2 条件更新字段

// 根据给定的条件更新单个属性
// UPDATE `users_updates` SET `name`='bak',`updated_at`='2021-11-23 22:56:37.193' WHERE active = false AND `users_updates`.`deleted_at` IS NULL AND `id` = 1

db.Debug().Model(&user).Where("active = ?", true).Update("name", "hello")

image-20211123225703195

image-20211123225723642

2.3 map 更新多个属性字段

// 使用 map 更新多个属性,只会更新其中有变化的属性
//UPDATE `users_updates` SET `active`=true,`age`=119,`name`='',`updated_at`='2021-11-24 08:24:03.114' WHERE `id` = 1

m1 := map[string]interface{}{
    "name":"",
    "age": 119,
    "active": true,

}
db.Debug().Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})

image-20211124082543045

image-20211124082525630

2.4 struct 更新多个属性

// 使用 struct 更新多个属性,只会更新其中有变化且为非零值的字段
//  UPDATE `users_updates` SET `updated_at`='2021-11-24 08:28:40.079',`name`='hello' WHERE `id` = 1
var user UsersUpdate
db.Debug().First(&user)
db.Debug().Model(&user).Updates(UsersUpdate{Name: "hello", Age: 0, Active: false})

// 警告:当使用 struct 更新时,GORM只会更新那些非零值的字段
// 对于下面的操作,不会发生任何更新,"", 0, false 都是其类型的零值
db.Debug().Model(&user).Updates(User{Name: "", Age: 0, Active: false})

image-20211124083012030

image-20211124083049901

2.5 更新选定字段

如果你想更新或忽略某些字段,你可以使用 SelectOmit

m1 := map[string]interface{}{
    "name":"",
    "age": 18,
    "active": true,

}
// UPDATE `users_updates` SET `age`=18,`updated_at`='2021-11-24 08:31:31.716' WHERE `id` = 1
// 只更新age字段
db.Debug().Model(&user).Select("age").Updates(m1)

2.6 更新排除字段

m1 := map[string]interface{}{
    "name":"Randy",
    "age": 188,
    "active": false,

}
// 排除m1中active更新其他的字段
//  UPDATE `users_updates` SET `age`=188,`name`='Randy',`updated_at`='2021-11-24 08:33:48.312' WHERE `id` = 1
db.Debug().Model(&user).Omit("active").Updates(m1)

image-20211124083428534

image-20211124083504638

2.7 无Hooks更新

上面的更新操作会自动运行 model 的 BeforeUpdate, AfterUpdate 方法,更新 UpdatedAt 时间戳, 在更新时保存其 Associations, 如果你不想调用这些方法,你可以使用 UpdateColumnUpdateColumns

// 更新单个属性,类似于 `Update`
db.Debug().Model(&user).UpdateColumn("name", "hello")
//// UPDATE users SET name='hello' WHERE id = 111;

// 更新多个属性,类似于 `Updates`
db.Debug().Model(&user).UpdateColumns(User{Name: "hello", Age: 18})
//// UPDATE users SET name='hello', age=18 WHERE id = 111;

三、 批量更新

批量更新时Hooks(钩子函数)不会运行。

// 批量更新
// UPDATE `users` SET `age`=18,`name`='xiao_zhi' WHERE id IN (3,4)
update_res := db.Debug().Table("users_updates").Where("id IN (?)", []int{3, 4}).Updates(map[string]interface{}{"name": "xiao_zhi", "age": 18})
fmt.Printf("%#v", update_res)

// 使用 `RowsAffected` 获取更新记录总数
rows := update_res.RowsAffected
fmt.Printf("%#v", rows)


// 使用 struct 更新时,只会更新非零值字段,若想更新所有字段,请使用map[string]interface{}
db.Debug().Model(User{}).Updates(User{Name: "hello", Age: 18})
//// UPDATE users SET name='hello', age=18;

// 使用 `RowsAffected` 获取更新记录总数
db.Debug().Model(User{}).Updates(User{Name: "hello", Age: 18}).RowsAffected

image-20211124084531391

image-20211124084420612

四、 使用SQL表达式更新

先查询表中的第一条数据保存至user变量。

4.1 查询更新

var user UsersUpdate
db.Debug().First(&user)
fmt.Printf("%#v", user)
// UPDATE `users_updates` SET `age`=age * 2 + 100,`updated_at`='2021-11-24 08:47:38.193' WHERE `id` = 1
db.Debug().Model(&user).Update("age", gorm.Expr("age * ? + ?", 2, 100))

image-20211124084959280

image-20211124085019639

4.2 map更新

var user UsersUpdate
db.Debug().First(&user)
fmt.Printf("%#v", user)
//  UPDATE `users_updates` SET `age`=age * 2 + 100,`updated_at`='2021-11-24 08:54:32.295' WHERE `id` = 1
db.Debug().Model(&user).Updates(map[string]interface{}{"age": gorm.Expr("age * ? + ?", 2, 100)})

image-20211124085511116

image-20211124085526432

4.3 UpdateColumn更新

var user UsersUpdate
db.Debug().First(&user)
fmt.Printf("%#v", user)
//  UPDATE `users_updates` SET `age`=age - 1 WHERE `id` = 1
db.Debug().Model(&user).UpdateColumn("age", gorm.Expr("age - ?", 1))

image-20211124085631686

image-20211124085648143

4.3 条件更新

var user UsersUpdate
db.Debug().First(&user)
fmt.Printf("%#v", user)
// UPDATE `users_updates` SET `age`=age - 1 WHERE age > 10 AND `users_updates`.`deleted_at` IS NULL AND `id` = 1
db.Debug().Model(&user).Where("age > 10").UpdateColumn("age", gorm.Expr("age - ?", 1))

image-20211124085826792

image-20211124085840916

4.4 修改Hooks中的值

如果你想修改 BeforeUpdate, BeforeSave 等 Hooks 中更新的值,你可以使用 scope.SetColumn, 例如:

func (user *User) BeforeSave(scope *gorm.Scope) (err error) {
  if pw, err := bcrypt.GenerateFromPassword(user.Password, 0); err == nil {
    scope.SetColumn("EncryptedPassword", pw)
  }
}

五、 其它更新选项

var user UsersUpdate
db.Debug().First(&user)
fmt.Printf("%#v", user)
// 为 update SQL 添加其它的 SQL
// UPDATE `users_updates` SET `name`='hello',`updated_at`='2021-11-24 09:01:16.859' WHERE `id` = 1
db.Debug().Model(&user).Set("gorm:update_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Update("name", "hello")

image-20211124090200431

image-20211124090213214

posted @ 2021-11-30 22:51  RandySun  阅读(502)  评论(0编辑  收藏  举报