#1,更新

#1,更新所有字段

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

 

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

// 1,定义模型
type User struct {
    ID     int64
    Name   string
    Age    int64
    Active bool
}

func main() {
    // 2, 连接数据库
    db, err := gorm.Open("mysql", "root:root1234@(127.0.0.1:13306)/db1?charset=utf8mb4&parseTime=True&loc=Local")
    if err != nil {
        panic(err)
    }
    defer db.Close()
    // 默认情况下,gorm创建的表将会是结构体名称的复数形式,如果不想让它自动复数,可以加一下禁用
    db.SingularTable(true)

    // 3, 把模型与数据库中的表对应起来
    db.AutoMigrate(&User{})

    // 4, 创建
    //u1 := User{Name: "eryajf", Age: 20, Active: true}
    //db.Create(&u1)
    //u2 := User{Name: "jinzhu", Age: 22, Active: false}
    //db.Create(&u2)

    // 5, 查询
    var user User
    db.First(&user)
    fmt.Println(user)

    // 6, 更新
    user.Name = "二丫讲梵"
    user.Age = 20
    // save 默认会更新该对象的所有字段,即使没有赋值
    db.Debug().Save(&user) //UPDATE `user` SET `name` = '二丫讲梵', `age` = 20, `active` = true  WHERE `user`.`id` = 1

}

#2,更新修改字段

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

 

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

// 1,定义模型
type User struct {
    ID     int64
    Name   string
    Age    int64
    Active bool
}

func main() {
    // 2, 连接数据库
    db, err := gorm.Open("mysql", "root:root1234@(127.0.0.1:13306)/db1?charset=utf8mb4&parseTime=True&loc=Local")
    if err != nil {
        panic(err)
    }
    defer db.Close()
    // 默认情况下,gorm创建的表将会是结构体名称的复数形式,如果不想让它自动复数,可以加一下禁用
    db.SingularTable(true)

    // 3, 把模型与数据库中的表对应起来
    db.AutoMigrate(&User{})

    // 4, 创建
    //u1 := User{Name: "eryajf", Age: 20, Active: true}
    //db.Create(&u1)
    //u2 := User{Name: "jinzhu", Age: 22, Active: false}
    //db.Create(&u2)

    // 5, 查询
    var user User
    db.First(&user)
    fmt.Println(user)

    // 6, 更新
    // 更新单个属性,如果他有变化
    db.Debug().Model(&user).Update("name", "hello") //UPDATE `user` SET `name` = 'hello'  WHERE `user`.`id` = 1

    // 根据给定的条件更新单个属性
    db.Debug().Model(&user).Where("active = ?", true).Update("name", "hello") //UPDATE `user` SET `name` = 'hello'  WHERE `user`.`id` = 1 AND ((active = true))

    // 使用map 更新多个属性,只会更新其中有变化的属性
    db.Debug().Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": "false"}) //UPDATE `user` SET `active` = true, `age` = 18, `name` = 'hello'  WHERE `user`.`id` = 1

    // 使用struct 更新多个属性,只会更新其中有变化且为非零值的字段
    db.Debug().Model(&user).Updates(User{Name: "hello", Age: 23}) //UPDATE `user` SET `age` = 23, `name` = 'hello'  WHERE `user`.`id` = 1

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

#3,更新选定字段

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

 

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

// 1,定义模型
type User struct {
    ID     int64
    Name   string
    Age    int64
    Active bool
}

func main() {
    // 2, 连接数据库
    db, err := gorm.Open("mysql", "root:root1234@(127.0.0.1:13306)/db1?charset=utf8mb4&parseTime=True&loc=Local")
    if err != nil {
        panic(err)
    }
    defer db.Close()
    // 默认情况下,gorm创建的表将会是结构体名称的复数形式,如果不想让它自动复数,可以加一下禁用
    db.SingularTable(true)

    // 3, 把模型与数据库中的表对应起来
    db.AutoMigrate(&User{})

    // 4, 创建
    //u1 := User{Name: "eryajf", Age: 20, Active: true}
    //db.Create(&u1)
    //u2 := User{Name: "jinzhu", Age: 22, Active: false}
    //db.Create(&u2)

    // 5, 查询
    var user User
    db.First(&user)
    fmt.Println(user)

    // 6, 更新
    m1 := map[string]interface{}{
        "name":   "liqilong",
        "age":    20,
        "active": true,
    }

    // 选择 m1 中某个字段进行更新
    db.Debug().Model(&user).Select("name").Updates(m1) //UPDATE `user` SET `name` = 'liqilong'  WHERE `user`.`id` = 1

    // 忽略 m1 中active字段更新其他字段
    db.Debug().Model(&user).Omit("active").Updates(m1) //UPDATE `user` SET `age` = 20, `name` = 'liqilong'  WHERE `user`.`id` = 1
}

#4,无Hooks更新

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

 

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

// 1,定义模型
type User struct {
    ID     int64
    Name   string
    Age    int64
    Active bool
}

func main() {
    // 2, 连接数据库
    db, err := gorm.Open("mysql", "root:root1234@(127.0.0.1:13306)/db1?charset=utf8mb4&parseTime=True&loc=Local")
    if err != nil {
        panic(err)
    }
    defer db.Close()
    // 默认情况下,gorm创建的表将会是结构体名称的复数形式,如果不想让它自动复数,可以加一下禁用
    db.SingularTable(true)

    // 3, 把模型与数据库中的表对应起来
    db.AutoMigrate(&User{})

    // 4, 创建
    //u1 := User{Name: "eryajf", Age: 20, Active: true}
    //db.Create(&u1)
    //u2 := User{Name: "jinzhu", Age: 22, Active: false}
    //db.Create(&u2)

    // 5, 查询
    var user User
    db.First(&user)
    fmt.Println(user)

    // 6, 更新

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

}

#5,批量更新

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

 

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

// 1,定义模型
type User struct {
    ID     int64
    Name   string
    Age    int64
    Active bool
}

func main() {
    // 2, 连接数据库
    db, err := gorm.Open("mysql", "root:root1234@(127.0.0.1:13306)/db1?charset=utf8mb4&parseTime=True&loc=Local")
    if err != nil {
        panic(err)
    }
    defer db.Close()
    // 默认情况下,gorm创建的表将会是结构体名称的复数形式,如果不想让它自动复数,可以加一下禁用
    db.SingularTable(true)

    // 3, 把模型与数据库中的表对应起来
    db.AutoMigrate(&User{})

    // 4, 创建
    //u1 := User{Name: "eryajf", Age: 20, Active: true}
    //db.Create(&u1)
    //u2 := User{Name: "jinzhu", Age: 22, Active: false}
    //db.Create(&u2)

    // 5, 查询
    var user User
    db.First(&user)
    fmt.Println(user)

    // 6, 更新

    db.Debug().Table("user").Where("id IN (?)", []int{10, 11}).Updates(map[string]interface{}{"name": "hello", "age": 20}) //UPDATE `user` SET `age` = 20, `name` = 'hello'  WHERE (id IN (10,11))
    // 使用struct更新时,只会更新非零值字段,若想更新所有字段,应使用如上map方式
    db.Debug().Model(User{}).Updates(User{Name: "hello", Age: 23}) //UPDATE `user` SET `age` = 23, `name` = 'hello'

    // 使用 RowsAffected 获取更新记录总数
    chageNum := db.Debug().Model(User{}).Updates(User{Name: "hello", Age: 23}).RowsAffected //UPDATE `user` SET `age` = 23, `name` = 'hello'
    fmt.Println(chageNum)

    //db.Debug().Model(&user)
}

#6,使用SQL表达式更新

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

 

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

// 1,定义模型
type User struct {
    ID     int64
    Name   string
    Age    int64
    Active bool
}

func main() {
    // 2, 连接数据库
    db, err := gorm.Open("mysql", "root:root1234@(127.0.0.1:13306)/db1?charset=utf8mb4&parseTime=True&loc=Local")
    if err != nil {
        panic(err)
    }
    defer db.Close()
    // 默认情况下,gorm创建的表将会是结构体名称的复数形式,如果不想让它自动复数,可以加一下禁用
    db.SingularTable(true)

    // 3, 把模型与数据库中的表对应起来
    db.AutoMigrate(&User{})

    // 4, 创建
    //u1 := User{Name: "eryajf", Age: 20, Active: true}
    //db.Create(&u1)
    //u2 := User{Name: "jinzhu", Age: 22, Active: false}
    //db.Create(&u2)

    // 5, 查询
    var user User
    db.First(&user)
    fmt.Println(user)

    // 6, 更新

    // 给匹配到的用户增加3岁
    db.Debug().Model(&user).Update("age", gorm.Expr("age + ?", 3)) //UPDATE `user` SET `age` = age + 3  WHERE `user`.`id` = 1
    // 以map的方式进行年龄运算
    db.Debug().Model(&user).Updates(map[string]interface{}{"age": gorm.Expr("age * ? + ?", 2, 100)}) //UPDATE `user` SET `age` = age * 2 + 100  WHERE `user`.`id` = 1
    // 年龄减法
    db.Debug().Model(&user).UpdateColumn("age", gorm.Expr("age - ?", "2")) //UPDATE `user` SET `age` = age - '2'  WHERE `user`.`id` = 1
    // 给符合查询条件的用户年龄-1
    db.Debug().Model(&user).Where("age > 10").UpdateColumn("age", gorm.Expr("age - ?", 1)) //UPDATE `user` SET `age` = age - 1  WHERE `user`.`id` = 1 AND ((age > 10))

}

#7,修改Hooks中的值

如果你想修改 BeforeUpdateBeforeSave 等 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)
  }
}

#8,其它更新选项

 

// 为 update SQL 添加其它的 SQL
db.Model(&user).Set("gorm:update_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Update("name", "hello")
//// UPDATE users SET name='hello', updated_at = '2013-11-17 21:34:10' WHERE id=111 OPTION (OPTIMIZE FOR UNKNOWN);

#2,删除

#1,删除记录

警告 删除记录时,请确保主键字段有值,GORM 会通过主键去删除记录,如果主键为空,GORM 会删除该 model 的所有记录。

 

// 删除现有记录
db.Delete(&email)
//// DELETE from emails where id=10;

// 为删除 SQL 添加额外的 SQL 操作
db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email)
//// DELETE from emails where id=10 OPTION (OPTIMIZE FOR UNKNOWN);

#2,批量删除

删除全部匹配的记录

 

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

// 定义模型
type User struct {
    gorm.Model
    Name   string
    Age    int64
    Active bool
}

func main() {
    db, err := gorm.Open("mysql", "root:root1234@(127.0.0.1:13306)/db1?charset=utf8mb4&parseTime=True&loc=Local")
    if err != nil {
        panic(err)
    }
    defer db.Close()
    // 默认情况下,gorm创建的表将会是结构体名称的复数形式,如果不想让它自动复数,可以加一下禁用
    db.SingularTable(true)

    // 2, 把模型与数据库中的表对应起来
    db.AutoMigrate(&User{})

    // 3, 创建
    //u1 := User{Name: "eryajf", Age: 20, Active: true}
    //  //db.Create(&u1)
    //  //u2 := User{Name: "jinzhu", Age: 22, Active: false}
    //  //db.Create(&u2)
    //  //u3 := User{Name: "eryajf2", Age: 20, Active: true}
    //  //db.Create(&u3)
    //  //u4 := User{Name: "jinzhu2", Age: 22, Active: false}
    //  //db.Create(&u4)

    // 删除符合条件的记录
    db.Debug().Where("name LIKE ?", "%jinzhu%").Delete(User{}) //UPDATE `user` SET `deleted_at`='2020-03-08 23:48:05'  WHERE `user`.`deleted_at` IS NULL AND ((name LIKE 'jinzhu'))
    // 与上边效果一样
    db.Debug().Delete(User{}, "name LIKE ?", "%jinzhu%") //UPDATE `user` SET `deleted_at`='2020-03-08 23:49:34'  WHERE `user`.`deleted_at` IS NULL AND ((name LIKE '%jinzhu%'))

}

#3,软删除

如果一个 model 有 DeletedAt 字段,他将自动获得软删除的功能! 当调用 Delete 方法时, 记录不会真正的从数据库中被删除, 只会将DeletedAt 字段的值会被设置为当前时间

 

db.Delete(&user)
//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;

// 批量删除
db.Where("age = ?", 20).Delete(&User{})
//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;

// 查询记录时会忽略被软删除的记录
db.Where("age = 20").Find(&user)
//// SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;

// Unscoped 方法可以查询被软删除的记录
db.Unscoped().Where("age = 20").Find(&users)
//// SELECT * FROM users WHERE age = 20;

#4,物理删除

 

// Unscoped 方法可以物理删除记录
db.Unscoped().Delete(&order)
//// DELETE FROM orders WHERE id=10;

代码示例:

 

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

// 定义模型
type User struct {
    gorm.Model
    Name   string
    Age    int64
    Active bool
}

func main() {
    db, err := gorm.Open("mysql", "root:root1234@(127.0.0.1:13306)/db1?charset=utf8mb4&parseTime=True&loc=Local")
    if err != nil {
        panic(err)
    }
    defer db.Close()
    // 默认情况下,gorm创建的表将会是结构体名称的复数形式,如果不想让它自动复数,可以加一下禁用
    db.SingularTable(true)

    // 2, 把模型与数据库中的表对应起来
    db.AutoMigrate(&User{})

    // 3, 创建
    //u1 := User{Name: "eryajf", Age: 20, Active: true}
    //  //db.Create(&u1)
    //  //u2 := User{Name: "jinzhu", Age: 22, Active: false}
    //  //db.Create(&u2)
    //  //u3 := User{Name: "eryajf2", Age: 20, Active: true}
    //  //db.Create(&u3)
    //  //u4 := User{Name: "jinzhu2", Age: 22, Active: false}
    //  //db.Create(&u4)

    // 批量删除
    db.Debug().Where("age = ?", 20).Delete(&User{}) //UPDATE `user` SET `deleted_at`='2020-03-08 23:53:03'  WHERE `user`.`deleted_at` IS NULL AND ((age = 20))

    // 查询记录时会忽略被软删除的记录
    var user User
    db.Debug().Where("age = 20").Find(&user) //SELECT * FROM `user`  WHERE `user`.`deleted_at` IS NULL AND ((age = 20))
    fmt.Println(user)

    // Unscoped 方法可以查询被软删除的记录
    db.Debug().Unscoped().Where("age = 20").Find(&user) //SELECT * FROM `user`  WHERE (age = 20)
    fmt.Println(user)

    // Unscoped 方法可以物理删除记录
    db.Debug().Unscoped().Delete(User{}, "name = ?", "eryajf") //DELETE FROM `user`  WHERE (name = 'eryajf')
}

#3,链式操作相关

#1,链式操作

Method Chaining,Gorm 实现了链式操作接口,所以你可以把代码写成这样:

 

// 创建一个查询
tx := db.Where("name = ?", "jinzhu")

// 添加更多条件
if someCondition {
  tx = tx.Where("age = ?", 20)
} else {
  tx = tx.Where("age = ?", 30)
}

if yetAnotherCondition {
  tx = tx.Where("active = ?", 1)
}

在调用立即执行方法前不会生成Query语句,借助这个特性你可以创建一个函数来处理一些通用逻辑。

#2,立即执行方法

Immediate methods ,立即执行方法是指那些会立即生成SQL语句并发送到数据库的方法, 他们一般是CRUD方法,比如:

CreateFirstFindTakeSaveUpdateXXXDeleteScanRowRows

这有一个基于上面链式方法代码的立即执行方法的例子:

 

tx.Find(&user)

生成的SQL语句如下:

 

SELECT * FROM users where name = 'jinzhu' AND age = 30 AND active = 1;

#3,范围

Scopes,Scope是建立在链式操作的基础之上的。

基于它,你可以抽取一些通用逻辑,写出更多可重用的函数库。

 

func AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
  return db.Where("amount > ?", 1000)
}

func PaidWithCreditCard(db *gorm.DB) *gorm.DB {
  return db.Where("pay_mode_sign = ?", "C")
}

func PaidWithCod(db *gorm.DB) *gorm.DB {
  return db.Where("pay_mode_sign = ?", "C")
}

func OrderStatus(status []string) func (db *gorm.DB) *gorm.DB {
  return func (db *gorm.DB) *gorm.DB {
    return db.Scopes(AmountGreaterThan1000).Where("status IN (?)", status)
  }
}

db.Scopes(AmountGreaterThan1000, PaidWithCreditCard).Find(&orders)
// 查找所有金额大于 1000 的信用卡订单

db.Scopes(AmountGreaterThan1000, PaidWithCod).Find(&orders)
// 查找所有金额大于 1000 的 COD 订单

db.Scopes(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find(&orders)
// 查找所有金额大于 1000 且已付款或者已发货的订单

#4,多个立即执行方法

Multiple Immediate Methods,在 GORM 中使用多个立即执行方法时,后一个立即执行方法会复用前一个立即执行方法的条件 (不包括内联条件) 。

 

db.Where("name LIKE ?", "jinzhu%").Find(&users, "id IN (?)", []int{1, 2, 3}).Count(&count)

生成的 Sql

 

SELECT * FROM users WHERE name LIKE 'jinzhu%' AND id IN (1, 2, 3)

SELECT count(*) FROM users WHERE name LIKE 'jinzhu%'

发表回复

后才能评论