gorm-更新

2022-02-10  本文已影响0人  玄德公笔记

1. save (更新/创建)

主键如果查到,更新数据
主键如果未查到,插入一条数据

    liuBei := xiShu {
        ID: 9,
        Name: "GuanYu",
        Age: 30,
    }
    db.Save(&liuBei)
package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)
type xiShu struct {
    ID int64
    Name string
    Age int64
}

func(xiShu) TableName() string {
    return "xi_shu"
}

func main() {

    db,_ := connect()
    defer db.Close()
    //db.CreateTable(&xiShu{})

    liuBei := xiShu {
        ID: 9,
        Name: "LiuBei",
        Age: 30,
    }
    db.Save(&liuBei)
}

func connect() (db *gorm.DB,err error) {
    db, err = gorm.Open("mysql", "root:40010355@tcp(127.0.0.1:3306)/crow?charset=utf8&parseTime=True&loc=Local")
    if err != nil {
        fmt.Printf(err.Error())
        defer db.Close()
    }else {
        fmt.Printf("OK\n")
        db.DB().SetMaxIdleConns(10)
        db.DB().SetMaxOpenConns(100)
    }
    return
}

2. Update(单列修改)

目前表:

mysql> select * from xi_shu;
+----+------------+------+
| id | name       | age  |
+----+------------+------+
|  1 | LiuBei     |   28 |
|  2 | GuanYu     |   22 |
|  3 | ZhangFei   |   20 |
|  4 | ZhaoYun    |   18 |
|  5 | ZhuGeLiang |   20 |
|  6 | MaChao     |   20 |
|  7 | PangTong   |   25 |
|  8 | HuangZhong |   35 |
+----+------------+------+
9 rows in set (0.01 sec)

2.1 根据主键修改单列

db.Model(&xiShu{ID: 2}).Update("name", "WuSheng")

结构体中我们设置了三个成员,后边演示中可以看到,只有主键的 ID=2生效

func main() {

    db,_ := connect()
    defer db.Close()
    user := xiShu {
        ID: 2,
        Name: "GuanYu",
        Age: 30,
    }
    //var users []xiShu
    result := db.Model(&user).Update("name", "WuSheng")
    fmt.Println(result.Value)
}

说明:
我想说的是,如果结构体定义了很多成员,只有第一个会生效
Name和Age 的值对定位没有影响。
因此,Age:30 依然会查到第二行,然后修改该行。

OK
&{2 WuSheng 30}

可见,result的值是 结构体 user 的值基础上,做了Update() 的修改

mysql> select * from xi_shu where id = 2;
+----+---------+------+
| id | name    | age  |
+----+---------+------+
|  2 | WuSheng |   22 |
+----+---------+------+
1 row in set (0.00 sec)

可见,表的数据中,仅按着Update()修改了name列的值
而age列没因为结构体user的Age值而改变,和输出中result的值不同。

2.2 全部行修改

按上边的结果,我们可以推测,要修改所有行的name值可以:

func main() {

    db,_ := connect()
    defer db.Close()
    result := db.Model(&xiShu{}).Update("name", "WuSheng")
    fmt.Println(result.Value)
}

2.3 使用组合条件更新单个属性

db.Model(&xiShu{}).Where("name = ?","GuanYu").Update("name", "WuSheng")

2.4 使用 map 更新多个属性

db.Model(&xiShu{}).Where("name = ?","GuanYu").Updates(map[string]interface{}{"name": "WuSheng", "age": 99})

2.5 使用 struct 更新多个属性

db.Model(&xiShu{}).Where("name = ?","GuanYu").Updates(&xiShu{Name: "WuSheng",Age: 99})

3. Updates

3.1 限制修改字段范围

func main() {
    db,_ := connect()
    defer db.Close()

    db.Model(&xiShu{ID:2}).Select("name").Updates(map[string]interface{}{"name": "WuSheng", "age": 99})
}

表修改结果:

mysql> select * from xi_shu;
+----+------------+------+
| id | name       | age  |
+----+------------+------+
|  1 | LiuBei     |   28 |
|  2 | WuSheng    |   22 |
|  3 | ZhangFei   |   20 |
|  4 | ZhaoYun    |   18 |
|  5 | ZhuGeLiang |   20 |
|  6 | MaChao     |   20 |
+----+------------+------+
6 rows in set (0.00 sec)

说明:Update()指定了name和age两个字段,但是Select限制了修改范围是name字段,因此age不会改变。

3.2 限制不修改字段

db.Model(&xiShu{ID:2}).Omit("name").Updates(map[string]interface{}{"name": "WuSheng", "age": 99})

表修改结果

mysql> select * from xi_shu;
+----+------------+------+
| id | name       | age  |
+----+------------+------+
|  1 | LiuBei     |   28 |
|  2 | GuanYu     |   99 |
|  3 | ZhangFei   |   20 |
|  4 | ZhaoYun    |   18 |
|  5 | ZhuGeLiang |   20 |
|  6 | MaChao     |   20 |
+----+------------+------+
6 rows in set (0.00 sec)

说明:Update()指定了name和age两个字段,但是Omit限制了修改范围是不能是name字段,因此age不会改变。

4. 不使用钩子

4.1 UpdateColumn/UpdateColumns

上文 2.3.中如果有钩子方法,则会使用钩子,如果不想使用钩子可用UpdateColumn或UpdateColumns。

db.Model(&xiShu{ID:2}).UpdateColumn("name", "WuSheng")
db.Model(&user).UpdateColumns(User{Name: "WuSheng", Age: 99})

如果使用Update修改,则会调用BeforeUpdate,则 name结果会被修改为BeforeUpdate的参数 HaHa
但使用了UpdateColumn则会执行UpdateColumn中制定的参数,修改nameWuSheng

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)
type xiShu struct {
    ID int64
    Name string
    Age int64
}

func(xiShu) TableName() string {
    return "xi_shu"
}
//钩子
func (LiuBei *xiShu) BeforeUpdate(scope *gorm.Scope) error {
    scope.SetColumn("Name", "HaHa")
    return nil
}


func main() {

    db,_ := connect()
    defer db.Close()
    //不使用钩子
    result := db.Model(&xiShu{ID:2}).UpdateColumn("name", "WuSheng")
    fmt.Println(result.Value)
}

func connect() (db *gorm.DB,err error) {
    db, err = gorm.Open("mysql", "root:40010355@tcp(127.0.0.1:3306)/crow?charset=utf8&parseTime=True&loc=Local")
    if err != nil {
        fmt.Printf(err.Error())
        defer db.Close()
    }else {
        fmt.Printf("OK\n")
        db.DB().SetMaxIdleConns(10)
        db.DB().SetMaxOpenConns(100)
    }
    return
}

4.2 批量修改不使用钩子

db.Table("users").Where("id IN (?)", []int{10, 11}).Update(age: 20)
mysql> select * from xi_shu;
+----+------------+------+
| id | name       | age  |
+----+------------+------+
|  1 | LiuBei     |   28 |
|  2 | WuSheng    |   10 |
|  3 | ZhangFei   |   20 |
|  4 | ZhaoYun    |   18 |
|  5 | ZhuGeLiang |   20 |
|  6 | MaChao     |   20 |
+----+------------+------+
6 rows in set (0.00 sec)

代码

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)
type xiShu struct {
    ID int64
    Name string
    Age int64
}

func(xiShu) TableName() string {
    return "xi_shu"
}

func (LiuBei *xiShu) BeforeUpdate(scope *gorm.Scope) error {
    scope.SetColumn("Age", 10)
    return nil
}


func main() {

    db,_ := connect()
    defer db.Close()

    result := db.Model(&xiShu{ID: 2}).Update("Age",9)
    fmt.Println(result.Value)
}

func connect() (db *gorm.DB,err error) {
    db, err = gorm.Open("mysql", "root:40010355@tcp(127.0.0.1:3306)/crow?charset=utf8&parseTime=True&loc=Local")
    if err != nil {
        fmt.Printf(err.Error())
        defer db.Close()
    }else {
        fmt.Printf("OK\n")
        db.DB().SetMaxIdleConns(10)
        db.DB().SetMaxOpenConns(100)
    }
    return
}

表修改结果

mysql> select * from xi_shu;
+----+------------+------+
| id | name       | age  |
+----+------------+------+
|  1 | LiuBei     |   28 |
|  2 | WuSheng    |   10 |
|  3 | ZhangFei   |   20 |
|  4 | ZhaoYun    |   18 |
|  5 | ZhuGeLiang |   20 |
|  6 | MaChao     |   20 |
+----+------------+------+
6 rows in set (0.00 sec)

BeforeUpdate参数年龄10,而Update参数年龄 9
结果可见,单行修改使用了BeforeUpdate参数10

func main() {

    db,_ := connect()
    defer db.Close()

    result := db.Table("xi_shu").Where("id IN (?)", []int{1,2,3}).Update("Age",9)
    fmt.Println(result.Value)
}

表修改结果

mysql> mysql> select * from xi_shu;
+----+------------+------+
| id | name       | age  |
+----+------------+------+
|  1 | LiuBei     |    9 |
|  2 | WuSheng    |    9 |
|  3 | ZhangFei   |    9 |
|  4 | ZhaoYun    |   18 |
|  5 | ZhuGeLiang |   20 |
|  6 | MaChao     |   20 |
+----+------------+------+
6 rows in set (0.00 sec)

如上可见,1、2、3行都修改为9,使用了Update参数,而不是BeforeUpdate的参数。
注意:即使where中id=1,也是多行修改,只不过是查到了一行而以,因此钩子不生效。

5. RowsAffected(修改影响行数)

func main() {

    db,_ := connect()
    defer db.Close()

    result := db.Table("xi_shu").Where("id IN (?)", []int{1,2,3}).Update("Age",11).RowsAffected
    fmt.Println(result)
}

输出

OK
3

1、2、3 三行被修改,输出为3。

6. Expr(带有表达式的sql更新)

将id=2 的用户 年龄X2+100

func main() {

    db,_ := connect()
    defer db.Close()

    result := db.Model(&xiShu{ID: 2}).Update("age", gorm.Expr("age * ? + ?", 2, 100))
    fmt.Println(result.Value)
}

表结果

mysql> select * from xi_shu where id = 2;
+----+---------+------+
| id | name    | age  |
+----+---------+------+
|  2 | WuSheng |  144 |
+----+---------+------+
1 row in set (0.00 sec)

如上,关羽的年龄从22修改为144

上一篇下一篇

猜你喜欢

热点阅读