本文章主要学习GORM的增删查改。若还没有完成数据库和数据表的创建、定义模型以及数据库的连接请先学习本本专栏文章Golang学习笔记之GORM基础使用(一)。本文为学习笔记,通过GORM官方中文文档和李文周的博客学习整理而成。

也可以使用原生sql语句。当然使用orm语句的便利点在于切换,可以切换不同的数据库。

目录

创建记录

基本操作

默认值

查询操作

基本查询

条件查询Where

结构体和Map查询

查询零值条件

NOT条件

Or条件

内联条件

额外查询选项

FirstOrInit

Attrs(找不到时使用)

Assign(不管找不找到都是用)

FirstOrCreate

Attrs(找不到时使用)

Assign(不管找不找到都是用)

检索相应字段

排序

数量

偏移

总数

更新操作

保存所有字段

更新单个列

更新多列

更新选定字段

更新 Hook

无Hooks更新

批量更新

删除操作

基本删除

根据主键删除

Delete Hook

批量删除

阻止全局删除

软删除

查找被软删除的记录


创建记录

官方文档创建链接:

创建 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.https://gorm.io/zh_CN/docs/create.html小技巧:在学习过程中要是有不理解的步骤可以通过Debug()(例如db.Debug().Create(&User))可以打印出对应的sql语句更好理解。

基本操作

1、先在代码层面创建一个User对象,此时数据中是没有这一条数据的。

2、使用db.Create()进行创建。注意在括号中要使用指针。

user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}  //在代码层面创建一个User对象result := db.Create(&user) // 通过数据的指针来创建user.ID             // 返回插入数据的主键
result.Error        // 返回 error
result.RowsAffected // 返回插入记录的条数

3、可以使用下述代码判断主键是否为空。通过返回值可以判断如果主键为空可以直接创建,若不为空说明该条数据已经存在,可以选择更改数据或者不做更改。

db.NewRecord(&user) 

默认值

在用户不传递这个值的时候就使用默认值进行代替。也就是所有字段的零值,比如0"",false或者其它零值,都不会保存到数据库内,但会使用他们的默认值。

 `gorm:"default:'xka'"`

放在代码中如下位置:

// UserInfo 用户信息
type UserInfo struct {    ID uint              Name string   `gorm:"default:'xka'"` //在name字段为空时,使用xka代替Gender stringHobby string
}//表示配置操作数据库的表名称,如果没有表名则是直接使用结构体的复数
func (UserInfo) TableName() string {return "userinfo"
}

注意:通过tag定义字段的默认值,在创建记录时候生成的 SQL 语句会排除没有值或值为 零值 的字段。 在将记录插入到数据库后,Gorm会从数据库加载那些字段的默认值。

若是设置了默认值之后想要保留空字符串时,可以考虑使用指针或实现 Scanner/Valuer接口。

1、使用指针方式

// 使用指针
type UserInfo struct {    ID uint              Name *string   `gorm:"default:'xka'"` //使用的是字符串的指针*stringGender stringHobby string
}user := User{Name: new(string), Age: 18))}  //new(string)空字符串的指针
db.Create(&user)  // 此时数据库中该条记录name字段的值就是''

2、使用实现 Scanner/Valuer接口

type UserInfo struct {    ID uint              Name sql.NullString   `gorm:"default:'xka'"` // sql.NullString 实现了Scanner/Valuer接口Gender stringHobby string
}user := User{Name: sql.NullString{"", true}, Age:18}
db.Create(&user)  // 此时数据库中该条记录name字段的值就是''

查询操作

官方文档查询链接:

查询 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.https://gorm.io/zh_CN/docs/query.html GORM 提供了 FirstTakeLast 方法,以便从数据库中检索单个对象。当查询数据库时它添加了 LIMIT 1 条件,且没有找到记录时,它会返回 ErrRecordNotFound 错误

基本查询

注意:以下几种要以id作为主键。

var user User
var users []User// 获取第一条记录(主键升序)
db.First(&user)
// SELECT * FROM users ORDER BY id LIMIT 1;// 获取一条记录,没有指定排序字段
db.Take(&user)
// SELECT * FROM users LIMIT 1;// 获取最后一条记录(主键降序)
db.Last(&user)
// SELECT * FROM users ORDER BY id DESC LIMIT 1;// 查询所有的记录
db.Find(&users)SELECT * FROM users;// 查询指定的某条记录(仅当主键为整型时可用)
db.First(&user, 10)SELECT * FROM users WHERE id = 10;result := db.First(&user)
result.RowsAffected // 返回找到的记录数
result.Error        // returns error or nil// 检查 ErrRecordNotFound 错误
errors.Is(result.Error, gorm.ErrRecordNotFound)

条件查询Where

// Get first matched record
db.Where("name = ?", "xka").First(&user)SELECT * FROM users WHERE name = 'xka' limit 1;// Get all matched records
db.Where("name = ?", "xka").Find(&users)SELECT * FROM users WHERE name = 'xka';// <>不等于
db.Where("name <> ?", "xka").Find(&users)SELECT * FROM users WHERE name <> 'xka';// IN在一个范围里面
db.Where("name IN (?)", []string{"xka", "xka2"}).Find(&users)SELECT * FROM users WHERE name in ('xka','xka2');// LIKE模糊查询
db.Where("name LIKE ?", "%xk%").Find(&users)SELECT * FROM users WHERE name LIKE '%xk%';// AND
db.Where("name = ? AND age >= ?", "xka", "22").Find(&users)SELECT * FROM users WHERE name = 'xka' AND age >= 22;// Time
db.Where("updated_at > ?", lastWeek).Find(&users)SELECT * FROM users WHERE updated_at > '2000-01-01 00:00:00';// BETWEEN
db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)SELECT * FROM users WHERE created_at BETWEEN '2000-01-01 00:00:00' AND '2000-01-08 00:00:00';

结构体和Map查询

// Struct
db.Where(&User{Name: "xka", Age: 20}).First(&user)SELECT * FROM users WHERE name = "xka" AND age = 20 LIMIT 1;// Map
db.Where(map[string]interface{}{"name": "xka", "age": 20}).Find(&users)SELECT * FROM users WHERE name = "xka" AND age = 20;// 主键的切片
db.Where([]int64{20, 21, 22}).Find(&users)SELECT * FROM users WHERE id IN (20, 21, 22);

注意:当通过结构体进行查询时,GORM将会只通过非零值字段查询,这意味着如果你的字段值为0''false或者其他零值时,将不会被用于构建查询条件。例如:

db.Where(&User{Name: "xka", Age: 0}).Find(&users)
// SELECT * FROM users WHERE name = "xka";
//age=0没有作为条件参与sql语句

查询零值条件

可以使用指针或实现Scanner/Valuer接口来避免这个问题。

        1、使用指针

// 使用指针
type User struct {gorm.ModelName stringAge  *int
}

        2、使用Scanner/Valuer接口

// 使用 Scanner/Valuer
type User struct {gorm.ModelName stringAge  sql.NullInt64  // sql.NullInt64 实现了 Scanner/Valuer 接口
}

NOT条件

作用与Where类似的情形如下:

db.Not("name", "jinzhu").First(&user)SELECT * FROM users WHERE name <> "jinzhu" LIMIT 1;// Not In
db.Not("name", []string{"jinzhu", "jinzhu 2"}).Find(&users)SELECT * FROM users WHERE name NOT IN ("jinzhu", "jinzhu 2");// Not In slice of primary keys
db.Not([]int64{1,2,3}).First(&user)SELECT * FROM users WHERE id NOT IN (1,2,3);db.Not([]int64{}).First(&user)SELECT * FROM users;// Plain SQL
db.Not("name = ?", "jinzhu").First(&user)SELECT * FROM users WHERE NOT(name = "jinzhu");// Struct
db.Not(User{Name: "jinzhu"}).First(&user)SELECT * FROM users WHERE name <> "jinzhu";

Or条件

db.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&users)SELECT * FROM users WHERE role = 'admin' OR role = 'super_admin';// Struct
db.Where("name = 'jinzhu'").Or(User{Name: "jinzhu 2"}).Find(&users)SELECT * FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2';// Map
db.Where("name = 'jinzhu'").Or(map[string]interface{}{"name": "jinzhu 2"}).Find(&users)SELECT * FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2';

内联条件

作用与Where查询类似,当内联条件与多个立即执行方法一起使用时, 内联条件不会传递给后面的立即执行方法(解释见下)。

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

// 根据主键获取记录 (只适用于整形主键)
db.First(&user, 23)SELECT * FROM users WHERE id = 23 LIMIT 1;// 根据主键获取记录, 如果它是一个非整形主键
db.First(&user, "id = ?", "string_primary_key")SELECT * FROM users WHERE id = 'string_primary_key' LIMIT 1;// Plain SQL
db.Find(&user, "name = ?", "jinzhu")SELECT * FROM users WHERE name = "jinzhu";db.Find(&users, "name <> ? AND age > ?", "jinzhu", 20)SELECT * FROM users WHERE name <> "jinzhu" AND age > 20;// Struct
db.Find(&users, User{Age: 20})SELECT * FROM users WHERE age = 20;// Map
db.Find(&users, map[string]interface{}{"age": 20})SELECT * FROM users WHERE age = 20;

额外查询选项

// 为查询 SQL 添加额外的 SQL 操作
db.Set("gorm:query_option", "FOR UPDATE").First(&user, 10)SELECT * FROM users WHERE id = 10 FOR UPDATE;

注:for update是一种行级锁,又叫排它锁,一旦用户对某个行施加了行级加锁,则该用户可以查询也可以更新被加锁的数据行,其它用户只能查询但不能更新被加锁的数据行.

FirstOrInit

获取匹配的第一条记录,否则根据给定的条件初始化一个新的对象 (仅支持 struct 和 map 条件)

// 未找到
db.FirstOrInit(&user, User{Name: "non_existing"})user -> User{Name: "non_existing"}// 找到
db.Where(User{Name: "xka"}).FirstOrInit(&user)user -> User{Id: 111, Name: "xka", Age: 20}
db.FirstOrInit(&user, map[string]interface{}{"name": "xka"})user -> User{Id: 111, Name: "xka", Age: 20}

Attrs(找不到时使用)

如果记录未找到,将使用参数初始化 struct. 给新建的对象添加其他属性值。

// 未找到
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrInit(&user)SELECT * FROM USERS WHERE name = 'non_existing';user -> User{Name: "non_existing", Age: 20}db.Where(User{Name: "non_existing"}).Attrs("age", 20).FirstOrInit(&user)SELECT * FROM USERS WHERE name = 'non_existing';user -> User{Name: "non_existing", Age: 20}// 找到
db.Where(User{Name: "xka"}).Attrs(User{Age: 30}).FirstOrInit(&user)SELECT * FROM USERS WHERE name = xka';user -> User{Id: 111, Name: "xka", Age: 20}

Assign(不管找不找到都是用)

不管记录是否找到,都将参数赋值给struct。

// 未找到
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrInit(&user)user -> User{Name: "non_existing", Age: 20}// 找到
db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 30}).FirstOrInit(&user)SELECT * FROM USERS WHERE name = jinzhu';user -> User{Id: 111, Name: "Jinzhu", Age: 30}

FirstOrCreate

获取匹配的第一条记录, 否则根据给定的条件创建一个新的记录 (仅支持 struct 和 map 条件)

// 未找到
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrCreate(&user)SELECT * FROM users WHERE name = 'non_existing';INSERT INTO "users" (name, age) VALUES ("non_existing", 20);user -> User{Id: 112, Name: "non_existing", Age: 20}// 找到
db.Where(User{Name: "jinzhu"}).Attrs(User{Age: 30}).FirstOrCreate(&user)SELECT * FROM users WHERE name = 'jinzhu';user -> User{Id: 111, Name: "jinzhu", Age: 20}

Attrs(找不到时使用)

如果记录未找到,将使用参数初始化 struct. 给新建的对象添加其他属性值。

 // 未找到
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrCreate(&user)SELECT * FROM users WHERE name = 'non_existing';INSERT INTO "users" (name, age) VALUES ("non_existing", 20);user -> User{Id: 112, Name: "non_existing", Age: 20}// 找到
db.Where(User{Name: "jinzhu"}).Attrs(User{Age: 30}).FirstOrCreate(&user)SELECT * FROM users WHERE name = 'jinzhu';user -> User{Id: 111, Name: "jinzhu", Age: 20}

Assign(不管找不找到都是用)

不管记录是否找到,都将参数赋值给struct。

// 未找到
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrCreate(&user)SELECT * FROM users WHERE name = 'non_existing';INSERT INTO "users" (name, age) VALUES ("non_existing", 20);user -> User{Id: 112, Name: "non_existing", Age: 20}// 找到
db.Where(User{Name: "xka"}).Assign(User{Age: 30}).FirstOrCreate(&user)SELECT * FROM users WHERE name = 'xka';UPDATE users SET age=30 WHERE id = 111;user -> User{Id: 111, Name: "xka", Age: 30}

检索相应字段

Select,指定你想从数据库中检索出的字段,默认会选择全部字段。

db.Select("name, age").Find(&users)SELECT name, age FROM users;db.Select([]string{"name", "age"}).Find(&users)SELECT name, age FROM users;db.Table("users").Select("COALESCE(age,?)", 42).Rows()SELECT COALESCE(age,'42') FROM users;

排序

db.Order("age desc, name").Find(&users)SELECT * FROM users ORDER BY age desc, name;// 多字段排序
db.Order("age desc").Order("name").Find(&users)SELECT * FROM users ORDER BY age desc, name;// 覆盖排序
db.Order("age desc").Find(&users1).Order("age", true).Find(&users2)SELECT * FROM users ORDER BY age desc; (users1)SELECT * FROM users ORDER BY age; (users2)

数量

db.Limit(3).Find(&users)SELECT * FROM users LIMIT 3;// -1 取消 Limit 条件
db.Limit(10).Find(&users1).Limit(-1).Find(&users2)SELECT * FROM users LIMIT 10; (users1)SELECT * FROM users; (users2)

偏移

Offset,指定开始返回记录前要跳过的记录数。

db.Offset(3).Find(&users)SELECT * FROM users OFFSET 3;// -1 取消 Offset 条件
db.Offset(10).Find(&users1).Offset(-1).Find(&users2)SELECT * FROM users OFFSET 10; (users1)SELECT * FROM users; (users2)

总数

Count,该 model 能获取的记录总数。

db.Where("name = ?", "xka").Or("name = ?", "xka2").Find(&users).Count(&count)SELECT * from USERS WHERE name = 'xka' OR name = 'xka2'; (users)SELECT count(*) FROM users WHERE name = 'xka' OR name = 'xka2'; (count)db.Model(&User{}).Where("name = ?", "xka").Count(&count)SELECT count(*) FROM users WHERE name = 'xka'; (count)db.Table("deleted_users").Count(&count)SELECT count(*) FROM deleted_users;db.Table("deleted_users").Select("count(distinct(name))").Count(&count)SELECT count( distinct(name) ) FROM deleted_users; (count)

注意 :Count 必须是链式查询的最后一个操作 ,因为它会覆盖前面的 SELECT,但如果里面使用了 count 时不会覆盖

更新操作

官方中文文档:

更新 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.https://gorm.io/zh_CN/docs/update.html

保存所有字段

Save 会保存所有的字段,即使字段是零值

//从数据库中查询出需要更改的数据
db.First(&user)
//给user修改值
user.Name = "jinzhu 2"
user.Age = 100
//将修改值保存到数据库中
db.Save(&user)
// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111;

更新单个列

当使用 Update 更新单列时,需要有一些条件,否则将会引起错误 ErrMissingWhereClause ,阻止全局更新。当使用 Model 方法,并且值中有主键值时,主键将会被用于构建条件。

阻止全局更新 :如果在没有任何条件的情况下执行批量更新,默认情况下,GORM 不会执行该操作,并返回 ErrMissingWhereClause 错误。对此,你必须加一些条件,或者使用原生 SQL,或者启用 AllowGlobalUpdate 模式

// 条件更新
db.Model(&User{}).Where("active = ?", true).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE active=true;// User 的 ID 是 `111`
db.Model(&user).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;// 根据条件和 model 的值进行更新
db.Model(&user).Where("active = ?", true).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true;

更新多列

Updates 方法支持 struct 和 map[string]interface{} 参数。当使用 struct 更新时,默认情况下,GORM 只会更新非零值的字段

// 根据 `struct` 更新属性,只会更新非零值的字段
db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;// 根据 `map` 更新属性
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET name='hello', age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

更新选定字段

更新时选定、忽略某些字段,您可以使用 SelectOmit

// Select with Map
// User's ID is `111`:
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET name='hello' WHERE id=111;db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "active": false})
// UPDATE users SET age=18, active=false, updated_at='2013-11-17 21:34:10' WHERE id=111;// Select with Struct (select zero value fields)
db.Model(&user).Select("Name", "Age").Updates(User{Name: "new_name", Age: 0})
// UPDATE users SET name='new_name', age=0 WHERE id=111;// Select all fields (select all fields include zero value fields)
db.Model(&user).Select("*").Updates(User{Name: "jinzhu", Role: "admin", Age: 0})// Select all fields but omit Role (select all fields include zero value fields)
db.Model(&user).Select("*").Omit("Role").Updates(User{Name: "jinzhu", Role: "admin", Age: 0})

更新 Hook

Hook :对象生命周期,Hook 是在创建、查询、更新、删除等操作之前、之后调用的函数。如果您已经为模型定义了指定的方法,它会在创建、更新、查询、删除时自动被调用。如果任何回调返回错误,GORM 将停止后续的操作并回滚事务。(事务)

func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {if u.readonly() {err = errors.New("read only user")}return
}// 在同一个事务中更新数据
func (u *User) AfterUpdate(tx *gorm.DB) (err error) {if u.Confirmed {tx.Model(&Address{}).Where("user_id = ?", u.ID).Update("verfied", true)}return
}

无Hooks更新

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

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

批量更新

如果您尚未通过 Model 指定记录的主键,则 GORM 会执行批量更新。

// 根据 struct 更新
db.Model(User{}).Where("role = ?", "admin").Updates(User{Name: "hello", Age: 18})
// UPDATE users SET name='hello', age=18 WHERE role = 'admin';// 根据 map 更新
db.Table("users").Where("id IN ?", []int{10, 11}).Updates(map[string]interface{}{"name": "hello", "age": 18})
// UPDATE users SET name='hello', age=18 WHERE id IN (10, 11);

使用 struct 更新时,只会更新非零值字段,若想更新所有字段,请使用map[string]interface{}。

db.Table("users").Where("id IN (?)", []int{10, 11}).Updates(map[string]interface{}{"name": "hello", "age": 18})UPDATE users SET name='hello', age=18 WHERE id IN (10, 11);// 使用 struct 更新时,只会更新非零值字段,若想更新所有字段,请使用map[string]interface{}
db.Model(User{}).Updates(User{Name: "hello", Age: 18})UPDATE users SET name='hello', age=18;// 使用 `RowsAffected` 获取更新记录总数
db.Model(User{}).Updates(User{Name: "hello", Age: 18}).RowsAffected

删除操作

官方中文文档:

删除 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.https://gorm.io/zh_CN/docs/delete.html

基本删除

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

此处的email已经提前有了id值。

// 删除现有记录
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);

根据主键删除

db.Delete(&User{}, 10)
// DELETE FROM users WHERE id = 10;db.Delete(&User{}, "10")
// DELETE FROM users WHERE id = 10;db.Delete(&users, []int{1,2,3})
// DELETE FROM users WHERE id IN (1,2,3);

Delete Hook

对于删除操作,GORM 支持 BeforeDeleteAfterDelete Hook,在删除记录时会调用这些方法 。

// 在同一个事务中更新数据
func (u *User) AfterDelete(tx *gorm.DB) (err error) {if u.Confirmed {tx.Model(&Address{}).Where("user_id = ?", u.ID).Update("invalid", false)}return
}

批量删除 

如果指定的值不包括主属性,那么 GORM 会执行批量删除,它将删除所有匹配的记录。

db.Where("email LIKE ?", "%jinzhu%").Delete(&Email{})
// DELETE from emails where email LIKE "%jinzhu%";db.Delete(&Email{}, "email LIKE ?", "%jinzhu%")
// DELETE from emails where email LIKE "%jinzhu%";

阻止全局删除

如果没有任何条件的情况下执行批量删除,GORM 不会执行该操作,返回ErrMissingWhereClaus错误。对此,你必须加一些条件,或者使用原生 SQL,或者启用 AllowGlobalUpdate 模式。

db.Delete(&User{}).Error // gorm.ErrMissingWhereClausedb.Where("1 = 1").Delete(&User{})
// DELETE FROM `users` WHERE 1=1db.Exec("DELETE FROM users")
// DELETE FROM usersdb.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&User{})
// DELETE FROM users

软删除

如果您的模型包含了一个 gorm.deletedat 字段(gorm.Model 已经包含了该字段),它将自动获得软删除的能力!拥有软删除能力的模型调用 Delete 时,记录不会从数据库被真正删除。但 GORM会将 DeletedAt 置为当前时间, 并且你不能再通过普通的查询方法找到该记录。

// user 的 ID 是 `111`
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;

如果不想引入 gorm.Model,可以这样启用软删除特性:

type User struct {ID      intDeleted gorm.DeletedAtName    string
}

查找被软删除的记录

可使用 Unscoped 找到被软删除的记录 。

db.Unscoped().Where("age = 20").Find(&users)
// SELECT * FROM users WHERE age = 20;

以上就是本次所有关于GORM的增删查改的学习,谢谢观看!如有什么错误请各位大神在评论区指出。

Golang学习笔记之GORM基础使用(二)相关推荐

  1. Golang学习笔记之GORM基础使用(一)

    本文章主要学习了GORM的基础知识,数据库的连接以及数据库表的建立的多种方法.本文为学习笔记,通过GORM官方中文文档和李文周的博客学习整理而成. gorm是一个使用Go语言编写的ORM框架.它文档齐 ...

  2. golang学习笔记(7)-gorm实现修改功能

    gorm实现修改功能 目录 gorm实现修改功能 准备工作 保存所有字段 更新单个列 更新多列 更新选定字段 批量更新 根据子查询进行更新 使用 SQL 表达式更新 准备工作 建立数据库连接 impo ...

  3. UE5学习笔记01(基础操作二)

    1.Outliner被翻译成"大纲". 2.当按住Shift键移动一个物体时,摄像机会追随被移动的物体,形成一种第三人称视角的感觉. 3.在Outliner中选择一个或者多个物体之 ...

  4. golang学习笔记(基础篇)

    LCY~~Golang学习笔记 一.Go语言开发环境 ##安装Go开发包以及VsCode Go开发包与vscode配置安装教程网址:https://www.liwenzhou.com/posts/Go ...

  5. 前端学习笔记之CSS3基础语法与盒模型(二)

    前端学习笔记之 CSS3基础语法与盒模型 CSS3简介 CSS(cascading style sheet,层叠式样式表)是用来给HTML标签添加样式的语言 CSS3是CSS的最新版本,增加了大量的样 ...

  6. 118云原生编程语言Golang学习笔记

    Golang学习笔记 文章目录 1.Go简介 1.1 简介 1.2 设计初衷 1.3 Golang vs Java 1.4 应用领域 1.5 用go语言的公司 2.Go下载和安装 2.1 开发工具 2 ...

  7. 吴恩达《机器学习》学习笔记七——逻辑回归(二分类)代码

    吴恩达<机器学习>学习笔记七--逻辑回归(二分类)代码 一.无正则项的逻辑回归 1.问题描述 2.导入模块 3.准备数据 4.假设函数 5.代价函数 6.梯度下降 7.拟合参数 8.用训练 ...

  8. 学习笔记之数据可视化(二)—— 页面布局(下)

    续上一章 2.7 地图区域(.map) 2.7.1 实现步骤: 2.8 用户统计模块 2.8.1 布局: 2.8.2 柱状图 2.9 订单模块 2.9.1 订单区域布局 2.9.2 订单区域(orde ...

  9. 学习笔记之数据可视化(二)——页面布局(上)

    ~续上一章 2. 项目页面布局 2.1 基础布局 2.1.1 PC端屏幕宽度适配设置 2.1.2 主体容器viewport背景图片 2.1.3 HTML结构 2.1.4 css样式代码 2.2 边框图 ...

最新文章

  1. c#_Func和Action委托简介
  2. 第一周冲刺_周三总结
  3. python怎么读取pdf为文本_python怎么读取pdf文本内容
  4. 51nod 2020 排序相减(暴力解法)
  5. window.onload 函数不执行处理
  6. 推荐系统-Task03离线物料系统的构建
  7. Python+Selenium+Edge浏览器安装与简单运行(1/2)
  8. 智能制造与数字化工厂
  9. Java并发编程之安全发布对象的四种方法
  10. 【计算机网络自顶向下方法】Web页面请求的历程
  11. 网络攻防技术——shellcode编写
  12. 微信小程序 人脸识别功能 代码 wx.faceDetect
  13. java bsh介绍_BeanShell简介
  14. 秒杀系统企业级实战应用之真实工业界案例视频
  15. 苹果电脑python编译器_Mac版-python环境配置(二):编译器pycharm下载安装
  16. python创建空字典什么意思_Python3基础 dict 创建字典 空字典
  17. 制定科学学习计划的重要性
  18. B站股权曝光:陈睿持股12.9%阿里持股7.9% 寻求双重主要上市
  19. uTorrent设置,防止出现磁盘负荷100%
  20. 80后,我们难忘的电视剧

热门文章

  1. 为何优秀的程序员不断离开?,中高级Java面试中你不得不会的知识点
  2. 听说RSI准的难以置信?
  3. Shoprxr 开源电商系统
  4. 微信小程序,实现首页弹框活动引导功能
  5. 通达oa php_PHP的版本选择 discuz x3.2 php版本 通达oa php版本 最新版
  6. 24点_24点研究_24点结论_python
  7. 搜索引擎常用技巧——英文资料篇
  8. 轻轨列车 light rail train
  9. 计算机视觉领域稍微容易中的期刊系列(二)1
  10. 三十行代码轻松破解山东理工大学教务系统的登录问题