gorm的CRUD | 青训营笔记

257 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天

1 删除

1.1 删除一条记录

对于DELETE FROM users WHERE id = 6的SQL语句对应的gorm代码

db.Debug().Where("id = ?", 6).Delete(new(User))
// DELETE FROM `users` WHERE id = 6

对于DELETE FROM users WHERE users.id = 5的SQL语句对应的gorm代码

db.Debug().Delete(User{}, 5)
// DELETE FROM `users` WHERE `users`.`id` = 5

1.2 删除多条记录

GORM 允许通过主键(可以是复合主键)和内联条件来删除对象,它可以使用数字(如以下例子。也可以使用字符串——译者注)。

根据主键删除一个或多个。

db.Debug().Delete(&User{}, []int{11, 12})
// DELETE FROM `users` WHERE `users`.`id` IN (11, 12)

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

db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&User{})
// DELETE FROM users

如果指定的值不包括主属性,那么 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%";

1.4 Delete HooK

Hook 是在创建、查询、更新、删除等操作之前、之后调用的函数。

对于删除操作,GORM 支持 BeforeDelete、AfterDelete Hook,在删除记录时会调用这些方法。这些方法需要在创建对象时实现。

func (u *User) BeforeDelete(tx *gorm.DB) (err error) {
	fmt.Println("User BeforeDelete执行了")
	return
}
func (u *User) AfterDelete(tx *gorm.DB) (err error) {
	fmt.Println("User AfterDelete执行了")
	return
}

2 更新

2.1 保存

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

// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', 
// updated_at = '2013-11-17 21:34:10' WHERE id=111;user.Name = "jinzhu 2"
user.Name = "jinzhu 2"
user.Age = 100
db.Save(&user)

2.2 更新一列

当使用 Update 更新单个列时,你需要指定条件,否则会返回 ErrMissingWhereClause 错误。

// 条件更新
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;

2.3 更新选定字段

在更新时选定使用 Select、忽略某些字段使用Omit。详情看下列例子。

// Select 和 Map
// User's ID is `111`:
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
// UPDATE users SET name='hello' WHERE id=111;

db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
// UPDATE users SET age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

// Select 和 Struct (可以选中更新零值字段)
db.Model(&result).Select("Name", "Age").Updates(User{Name: "new_name", Age: 0})
// UPDATE users SET name='new_name', age=0 WHERE id=111;

3 查询

原生查询 SQL 和 Scan

查询参数映射

db.Where("name1 = @name OR name2 = @name", 
         map[string]interface{}{"name": "jinzhu2"}).First(&result3)
// SELECT * FROM `users` 
// WHERE name1 = "jinzhu2" OR name2 = "jinzhu2" ORDER BY `users`.`id` LIMIT 1

根据Struct和Map查询

// Struct
db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
// SELECT * FROM users WHERE name = "jinzhu" AND age = 20 ORDER BY id LIMIT 1;

// Map
db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
// SELECT * FROM users WHERE name = "jinzhu" AND age = 20;

4 新增

4.1 新增一条数据

使用model来快速新增一条数据。也可以使用Select和Omit来指定和排除字段。

user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}

result := db.Create(&user) // 通过数据的指针来创建

user.ID             // 返回插入数据的主键
result.Error        // 返回 error
result.RowsAffected // 返回插入记录的条数

4.2 批量新增

要有效地插入大量记录,可以将一个 slice 传递给 Create 方法。 将切片数据传递给 Create 方法,GORM 将生成一个单一的 SQL 语句来插入所有数据,并回填主键的值,钩子方法也会被调用。

var users = []User{{Name: "jinzhu1"}, {Name: "jinzhu2"}, {Name: "jinzhu3"}}
db.Create(&users)

for _, user := range users {
  user.ID // 1,2,3
}