// 若想在更新时跳过钩子方法且不追踪更新时间,可使用 UpdateColumn、UpdateColumns 方法 // 更新单个列 db.Model(&user).UpdateColumn("name", "hello") // UPDATE users SET name='hello' WHERE id = 111; // 更新多个列 db.Model(&user).UpdateColumns(User{Name: "hello", Age: 18}) // UPDATE users SET name='hello', age=18 WHERE id = 111; // 更新特定列 db.Model(&user).Select("name", "age").UpdateColumns(User{Name: "hello", Age: 0}) // UPDATE users SET name='hello', age=0 WHERE id = 111; // -------------------------------------------------------------------------- 检查字段是否被改变 // Changed 方法可以被用在 BeforeUpdate 钩子中,它返回字段是否有变更的布尔值 // Changed 方法只能与 Update、Updates 方法一起使用 // 并且它只检查 Model 对象字段的值与 Update、Updates 的值是否相等,若值有变更且字段没有被忽略,则返回 true func (u *User) BeforeUpdate(tx *gorm.DB) (err error) { // 若 Role 字段有变更 if tx.Statement.Changed("Role") { return errors.New("role not allowed to change") } // 若 Name 或 Role 字段有变更 if tx.Statement.Changed("Name", "Admin") { tx.Statement.SetColumn("Age", 18) } // 若任意字段有变更 if tx.Statement.Changed() { tx.Statement.SetColumn("RefreshedAt", time.Now()) } return nil } db.Model(&User{ID: 1, Name: "jinzhu"}).Updates(map[string]interface{"name": "jinzhu2"}) // Changed("Name") => true db.Model(&User{ID: 1, Name: "jinzhu"}).Updates(map[string]interface{"name": "jinzhu"}) // Changed("Name") => false, 因为 `Name` 没有变更 db.Model(&User{ID: 1, Name: "jinzhu"}).Select("Admin").Updates(map[string]interface{ "name": "jinzhu2", "admin": false, }) // Changed("Name") => false, 因为 `Name` 没有被 Select 选中并更新 db.Model(&User{ID: 1, Name: "jinzhu"}).Updates(User{Name: "jinzhu2"}) // Changed("Name") => true db.Model(&User{ID: 1, Name: "jinzhu"}).Updates(User{Name: "jinzhu"}) // Changed("Name") => false, 因为 `Name` 未变更 db.Model(&User{ID: 1, Name: "jinzhu"}).Select("Admin").Updates(User{Name: "jinzhu2"}) // Changed("Name") => false, 因为 `Name` 没有被 Select 选中并更新 // -------------------------------------------------------------------------- 在 Update 时修改值 // 若要在 Before 钩子中改变要更新的值 // 如果它是一个完整的更新,可以使用 Save,否则,应使用 SetColumn,例如: func (user *User) BeforeSave(tx *gorm.DB) (err error) { if pw, err := bcrypt.GenerateFromPassword(user.Password, 0); err == nil { tx.Statement.SetColumn("EncryptedPassword", pw) } if tx.Statement.Changed("Code") { user.Age += 20 tx.Statement.SetColumn("Age", user.Age) } } db.Model(&user).Update("Name", "jinzhu") // -------------------------------------------------------------------------- 在 Update 时修改值 // 可以在 BeforeSave 钩子中改变要更新的值 // 如果它是一个完整的更新,则可以使用 Save 方法,否则应使用 SetColumn 方法,例如: func (user *User) BeforeSave(tx *gorm.DB) (err error) { if pw, err := bcrypt.GenerateFromPassword(user.Password, 0); err == nil { tx.Statement.SetColumn("EncryptedPassword", pw) } if tx.Statement.Changed("Code") { user.Age += 20 tx.Statement.SetColumn("Age", user.Age) } } db.Model(&user).Update("Name", "jinzhu")