这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
GORM的CRUD接口
1、创建
1.1、创建记录
db.NewRecord (product): 用于检查主键是否为空.
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
db.NewRecord(user) //返回 `true` ,因为主键为空
db.Create(&user)
db.NewRecord(user) // 在 `user` 创建之后返回 `false`
1.2、为结构体字段指定默认值
可以通过标签定义字段的默认值,例如:
type Person struct {
ID int64
Name string `gorm:"default:'galeone'"`
Age int64
}
var person = Person{Age: 99, Name: ""}
db.Create(&person)
// INSERT INTO persons("age") values('99');
// SELECT name from persons WHERE ID=111; // 返回的主键是 111
// person.Name => 'galeone'
SQL 会排除那些没有值或者有零值的字段,在记录插入数据库之后,gorm将从数据库中加载这些字段的值。
2、查询
2.1、简单查询
获取第一条记录,按主键排序:
db.First(&user)
// SQL:SELECT * FROM users ORDER BY id LIMIT 1;
获取一条记录,不指定排序:
db.Take(&user)
// SQL:SELECT * FROM users LIMIT 1;
获取最后一条记录,按主键排序:
db.Last(&user)
// SQL:SELECT * FROM users ORDER BY id DESC LIMIT 1;
获取所有的记录:
db.Find(&users)
// SQL:SELECT * FROM users;
通过主键进行查询,适用于主键是数字类型:
db.First(&user, 10)
// SQL:SELECT * FROM users WHERE id = 10;
2.2、条件查询——where
获取第一条匹配的记录:
db.Where("name = ?", "jinzhu").First(&user)
// SQL:SELECT * FROM users WHERE name = 'jinzhu' limit 1;\
获取所有匹配的记录:
db.Where("name = ?", "jinzhu").Find(&users)
// SQL:SELECT * FROM users WHERE name = 'jinzhu';
带其它关键字:
// <>:
db.Where("name <> ?", "jinzhu").Find(&users)
// IN:
db.Where("name in (?)", []string{"jinzhu", "jinzhu 2"}).Find(&users)
// LIKE:
db.Where("name LIKE ?", "%jin%").Find(&users)
// AND:
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
// Time:
db.Where("updated_at > ?", lastWeek).Find(&users)
// BETWEEN:
db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users)
Struct & Map,通过struct进行查询的时候,GORM 将会查询这些字段的非零值, 意味着你的字段包 含 0 , '' , false 或者其他 零值, 将不会出现在查询语句中:
// Struct
db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
// SQL:SELECT * FROM users WHERE name = "jinzhu" AND age = 20 LIMIT 1;
// Map
db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
// SQL:SELECT * FROM users WHERE name = "jinzhu" AND age = 20;
// 多主键 slice 查询
db.Where([]int64{20, 21, 22}).Find(&users)
// SQL:SELECT * FROM users WHERE id IN (20, 21, 22);
2.3、Not
db.Not("name", "jinzhu").First(&user)
// SQL:SELECT * FROM users WHERE name <> "jinzhu" LIMIT 1;
// 不包含
db.Not("name", []string{"jinzhu", "jinzhu 2"}).Find(&users)
// SQL:SELECT * FROM users WHERE name NOT IN ("jinzhu", "jinzhu 2");
//不在主键 slice 中
db.Not([]int64{1,2,3}).First(&user)
// SQL:SELECT * FROM users WHERE id NOT IN (1,2,3);
db.Not([]int64{}).First(&user)
// SQL:SELECT * FROM users;
// 原生 SQL
db.Not("name = ?", "jinzhu").First(&user)
// SQL:SELECT * FROM users WHERE NOT(name = "jinzhu");
// Struct
db.Not(User{Name: "jinzhu"}).First(&user)
// SQL:SELECT * FROM users WHERE name <> "jinzhu";
2.4、Or
db.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&users)
// SQL:SELECT * FROM users WHERE role = 'admin' OR role = 'super_admin';
// Struct
db.Where("name = 'jinzhu'").Or(User{Name: "jinzhu 2"}).Find(&users)
// SQL:SELECT * FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2';
// Map
db.Where("name = 'jinzhu'").Or(map[string]interface{}{"name": "jinzhu 2"}).Find
(&users)
// SQL:SELECT * FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2';
3、高级查询
3.1、要从数据库检索指定的字段,默认情况下,将选择所有字段
db.Select("name, age").Find(&users)
// SQL:SELECT name, age FROM users;
db.Select([]string{"name", "age"}).Find(&users)
// SQL:SELECT name, age FROM users;
db.Table("users").Select("COALESCE(age,?)", 42).Rows()
// SQL:SELECT COALESCE(age,'42') FROM users;
3.2、Order-By:排序
使用 Order 从数据库查询记录,当第二个参数设置为 true 时,将会覆盖之前的定义条件。
db.Order("age desc, name").Find(&users)
// SQL:SELECT * FROM users ORDER BY age desc, name;
// 多个排序条件
db.Order("age desc").Order("name").Find(&users)
// SQL:SELECT * FROM users ORDER BY age desc, name;
// 重新排序
db.Order("age desc").Find(&users1).Order("age", true).Find(&users2)
// SQL:SELECT * FROM users ORDER BY age desc; (users1)
// SQL:SELECT * FROM users ORDER BY age; (users2)
3.3、Limit——分页查询
指定要查询的最大记录数:
db.Limit(3).Find(&users)
// SQL:SELECT * FROM users LIMIT 3;
// 用 -1 取消 LIMIT 限制条件
db.Limit(10).Find(&users1).Limit(-1).Find(&users2)
// SQL:SELECT * FROM users LIMIT 10; (users1)
// SQL:SELECT * FROM users; (users2)
3.4、Scan
将查询结果放入另一个结构体中。
type Result struct {
Name string
Age int
}
var result Result
db.Table("users").Select("name, age").Where("name = ?", 3).Scan(&result)
4、更新
4.1、更新所有字段
Save 方法:在执行 SQL 更新操作时将包含所有字段,即使这些字段没有被修改
db.First(&user)
user.Name = "jinzhu 2"
user.Age = 100
db.Save(&user)
// SQL:UPDATE users SET name='jinzhu 2', age=100, birthday='2023-1-17', updated_at = '2023-1-17 21:34:10' WHERE id=111;
4.2、更新选中的字段
如果在执行更新操作时只想更新或者忽略某些字段,可以使用 Select,Omit 方法。
db.Model(&user).Select("name").Updates(map[string]interface{}{"name": "hello","age": 18,"actived": false})
// SQL:UPDATE users SET name='hello', updated_at='2023-1-17 21:34:10' WHERE id=111;
db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
//SQL: UPDATE users SET age=18, actived=false, updated_at='2023-1-17 21:34:10' WHERE id=111;
4.3、更新已更改的字段
如果你只想更新已经修改了的字段,可以使用 Update , Updates 方法。
// 如果单个属性被更改了,更新它
db.Model(&user).Update("name", "hello")
// SQL:UPDATE users SET name='hello', updated_at='2023-1-17 21:34:10' WHERE id=111;
// 使用组合条件更新单个属性
db.Model(&user).Where("active = ?", true).Update("name", "hello")
// SQL:UPDATE users SET name='hello', updated_at='2023-1-17 21:34:10' WHERE id=111 AND active=true;
// 使用 `map` 更新多个属性,只会更新那些被更改了的字段
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
// SQL:UPDATE users SET name='hello', age=18, actived=false, updated_at='2023-1-17 21:34:10' WHERE id=111;
// 使用 `struct` 更新多个属性,只会更新那些被修改了的和非空的字段
db.Model(&user).Updates(User{Name: "hello", Age: 18})
// SQL:UPDATE users SET name='hello', age=18, updated_at = '2023-1-17 21:34:10' WHERE id = 111;
//当使用结构体更新的时候, GORM 只会更新那些非空的字段
// 例如下面的更新,没有东西会被更新,因为像 "", 0, false 是这些字段类型的空值
db.Model(&user).Updates(User{Name: "", Age: 0, Actived: false})
5、删除
5.1、删除记录
注意:当删除一条记录的时候,你需要确定这条记录的主键有值,GORM会使用主键来删除这 条记录。如果主键字段为空,GORM会删除模型中所有的记录
// 删除一条存在的记录
db.Delete(&email)
// SQL:DELETE from emails where id=10;
// 为删除 SQL 语句添加额外选项
db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email)
// SQL:DELETE from emails where id=10 OPTION (OPTIMIZE FOR UNKNOWN);
5.2、批量删除:删除所有匹配的记录
db.Where("email LIKE ?", "%jinzhu%").Delete(Email{})
// SQL:DELETE from emails where email LIKE "%jinzhu%";
db.Delete(Email{}, "email LIKE ?", "%jinzhu%")
// SQL:DELETE from emails where email LIKE "%jinzhu%";
5.3、软删除
如果模型中有 DeletedAt 字段,它将自动拥有软删除的能力!当执行删除操作时,数据并
不会永久的从数据库中删除,而是将 DeletedAt 的值更新为当前时间。
db.Delete(&user)
// SQL:UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;
// 批量删除
db.Where("age = ?", 20).Delete(&User{})
// SQL:UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;
// 在查询记录时,软删除记录会被忽略
db.Where("age = 20").Find(&user)
// SQL:SELECT * FROM users WHERE age = 20 AND deleted_at IS NULL;
// 使用 Unscoped 方法查找软删除记录
db.Unscoped().Where("age = 20").Find(&users)
// SQL:SELECT * FROM users WHERE age = 20;
// 使用 Unscoped 方法永久删除记录
db.Unscoped().Delete(&order)
//SQL: DELETE FROM orders WHERE id=10;