gorm 基本操作
编辑于 2022-09-04 22:39:25 阅读 999
type Test struct {
Id int `json:"id"`
Name string `json:"name"`
Memo string `json:"memo"`
CreateTime string `json:"create_time"`
UpdateTime string `json:"update_time"`
DeleteTime string `json:"delete_time"`
}
// 设置表名
func (Test) TableName() string {
return "cw_test"
}
查询
检索单个对象
- First:获取第一条记录(主键升序)
- Take:获取一条记录,没有指定排序字段
- Last:获取最后一条记录(主键降序)
下面以 First 为例,第一种:
test := &Test{}
result := orm.Db.First(&test)
fmt.Println(result.RowsAffected) //返回找到的记录数: 0 or 1
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
fmt.Println("not found")
return
}
data, _ := json.Marshal(&test)
fmt.Printf("%s\n", data)
第二种:
result := map[string]interface{}{}
orm.Db.Model(&Test{}).First(&result)
data, _ := json.Marshal(&result)
fmt.Printf("%s\n", data)
输出
{"create_time":"0","delete_time":"0","id":1,"memo":"b","name":"a","update_time":"0"}
用主键检索
//test := &Test{}
//result := orm.Db.First(&test, 2)
//result := orm.Db.First(&test, "name = ?", "aa")
test := &Test{Id: 2}
result := orm.Db.First(&test)
fmt.Println(result.RowsAffected) //返回找到的记录数: 0 or 1
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
fmt.Println("not found")
return
}
data, _ := json.Marshal(&test)
fmt.Printf("%s\n", data)
//db.Model()
var result Test
orm.Db.Model(Test{Id: 2}).First(&result)
data, _ := json.Marshal(&result)
fmt.Printf("%s\n", data)
输出
{"id":2,"name":"aa","memo":"bb","create_time":"0","update_time":"0","delete_time":"0"}
find(in)
var tests []*Test
orm.Db.Find(&tests, []int{1, 2, 3})
data, _ := json.Marshal(&tests)
fmt.Printf("%s\n", data)
输出
[{"id":1,"name":"a","memo":"b","create_time":"0","update_time":"0","delete_time":"0"},{"id":2,"name":"aa","memo":"bb","create_time":"0","update_time":"0","delete_time":"0"}]
检索全部对象
无条件查全部
var tests []*Test
result := orm.Db.Find(&tests)
fmt.Println(result.RowsAffected) //返回找到的记录总数
if result.Error != nil {
fmt.Println("not found")
return
}
data, _ := json.Marshal(&tests)
fmt.Printf("%s\n", data)
输出
[{"id":1,"name":"a","memo":"b","create_time":"0","update_time":"0","delete_time":"0"},{"id":2,"name":"aa","memo":"bb","create_time":"0","update_time":"0","delete_time":"0"}]
条件
String 条件
var tests []*Test
result := orm.Db.Where("name <> ?", "jinzhu").Find(&tests)
//result := orm.Db.Where("name IN ?", []string{"jinzhu", "jinzhu 2"}).Find(&tests)
//result := orm.Db.Where("name LIKE ?", "%jin%").Find(&tests)
//result := orm.Db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&tests)
//result := orm.Db.Where("updated_at > ?", lastWeek).Find(&tests)
//result := orm.Db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&tests)
fmt.Println(result.RowsAffected) //返回找到的记录总数
if result.Error != nil {
fmt.Println("not found")
return
}
data, _ := json.Marshal(&tests)
fmt.Printf("%s\n", data)
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;
// Slice of primary keys
db.Where([]int64{20, 21, 22}).Find(&users)
// SELECT * FROM users WHERE id IN (20, 21, 22);
注意:字段值为0,",false或其他零值,将不会用于构建查询条件。要在查询条件中包含0值,可以使用map,它将包含所有键值作为查询条件
db.Where(&User{Name: "jinzhu", Age: 0}).Find(&users)
// SELECT * FROM users WHERE name = "jinzhu";
db.Where(map[string]interface{}{"Name": "jinzhu", "Age": 0}).Find(&users)
// SELECT * FROM users WHERE name = "jinzhu" AND age = 0;
指定结构体查询字段
db.Where(&User{Name: "jinzhu"}, "name", "Age").Find(&users)
// SELECT * FROM users WHERE name = "jinzhu" AND age = 0;
db.Where(&User{Name: "jinzhu"}, "Age").Find(&users)
// SELECT * FROM users WHERE age = 0;
创建
创建记录
test := Test{Name: "zhangshan3", Memo: "真棒3", CreateTime: helper.GetUnix()}
result := orm.Db.Create(&test)
//result := orm.Db.Select("Name", "CreateTime").Create(&test) //除了Name,CreateTime,其他字段为空
//result := orm.Db.Omit("Memo").Create(&test) //填充所有字段,除了Memo
fmt.Println(test.Id) //返回插入数据的主键
fmt.Println(result.RowsAffected) //返回找到的记录总数
if result.Error != nil {
fmt.Println("insert error")
return
}
data, _ := json.Marshal(&test)
fmt.Printf("%s\n", data)
批量插入
tests := []Test{{Name: "jinzhu1"}, {Name: "jinzhu2", CreateTime: helper.GetUnix()}, {Name: "heihei"}}
result := orm.Db.Create(&tests)
//result := orm.Db.CreateInBatches(tests, 2) //分批创建,一批2个
for _, user := range tests {
fmt.Println(user.Id) // 1,2,3
}
fmt.Println(result.RowsAffected) //返回找到的记录总数
if result.Error != nil { //某条数据出错,将导致全部错误,但mysql的主键会被占用
fmt.Println("insert error")
return
}
data, _ := json.Marshal(&tests)
fmt.Printf("%s\n", data)
创建钩子
GORM 允许用户定义的钩子有 BeforeSave, BeforeCreate, AfterSave, AfterCreate 创建记录时将调用这些钩子方法
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
u.UUID = uuid.New()
if u.Role == "admin" {
return errors.New("invalid role")
}
return
}
如果您想跳过 钩子 方法,您可以使用 SkipHooks 会话模式,例如:
DB.Session(&gorm.Session{SkipHooks: true}).Create(&user)
DB.Session(&gorm.Session{SkipHooks: true}).Create(&users)
DB.Session(&gorm.Session{SkipHooks: true}).CreateInBatches(users, 100)
根据 Map 创建
result := orm.Db.Model(&Test{}).Create(map[string]interface{}{
"Name": "jinzhu", "Memo": "真棒3",
})
fmt.Println(result.RowsAffected) //返回找到的记录总数
if result.Error != nil {
fmt.Println("insert error")
return
}
// batch insert from `[]map[string]interface{}{}`
db.Model(&User{}).Create([]map[string]interface{}{
{"Name": "jinzhu_1", "Age": 18},
{"Name": "jinzhu_2", "Age": 20},
})
更新
Save 是保存所有字段,你需要先查出来(test),在test的基础上修改
test := Test{Id: 21}
orm.Db.First(&test)
test.Name = "jinzhu up.."
test.Memo = "up.."
test.UpdateTime = helper.GetUnix()
result := orm.Db.Save(&test)
//result := orm.Db.Table("cw_test").Where("id = ?", 21).Update("name", "hello")
fmt.Println(result.RowsAffected) //返回找到的记录总数
if result.Error != nil {
fmt.Println("update error")
return
}
data, _ := json.Marshal(&test)
fmt.Printf("%s\n", data)
更新单个列,Update 为部分更新
test := Test{Id: 21}
result := orm.Db.Model(&test).Update("name", "hello222")
fmt.Println(result.RowsAffected) //返回找到的记录总数
if result.Error != nil {
fmt.Println("update error")
return
}
data, _ := json.Marshal(&test)
fmt.Printf("%s\n", data)
// 条件更新
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;
// 根据条件和 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 只会更新非零值的字段
test := Test{Id: 21}
result := orm.Db.Model(&test).Updates(Test{Name: "hello33", Memo: "hhh", UpdateTime: helper.GetUnix()})
//result := orm.Db.Model(&test).Updates(map[string]interface{}{"name": "hello", "Memo": 18})
fmt.Println(result.RowsAffected) //返回找到的记录总数
if result.Error != nil {
fmt.Println("update error")
return
}
data, _ := json.Marshal(&test)
fmt.Printf("%s\n", data)
注意 当通过 struct 更新时,GORM 只会更新非零字段。
更新选定字段
如果您想要在更新时选定、忽略某些字段,您可以使用 Select、Omit
test := Test{Id: 21}
result := orm.Db.Model(&test).Select("Name", "Memo").Updates(Test{Name: "new_name", Memo: "0"})
fmt.Println(result.RowsAffected) //返回找到的记录总数
if result.Error != nil {
fmt.Println("update error")
return
}
data, _ := json.Marshal(&test)
fmt.Printf("%s\n", data)
// 使用 Map 进行 Select
// 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;
// 使用 Struct 进行 Select(会 select 零值的字段)
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 所有字段(查询包括零值字段的所有字段)
db.Model(&user).Select("*").Update(User{Name: "jinzhu", Role: "admin", Age: 0})
// Select 除 Role 外的所有字段(包括零值字段的所有字段)
db.Model(&user).Select("*").Omit("Role").Update(User{Name: "jinzhu", Role: "admin", Age: 0})
更新 Hook
对于更新操作,GORM 支持 BeforeSave、BeforeUpdate、AfterSave、AfterUpdate 钩子,这些方法将在更新记录时被调用
func (u *User) BeforeUpdate(tx *gorm.DB) (err error) {
if u.Role == "admin" {
return errors.New("admin user not allowed to update")
}
return
}
批量更新
无主键更新
result := orm.Db.Model(Test{}).Where("name = ?", "new_name").Updates(Test{Name: "new_name", Memo: "10"})
fmt.Println(result.RowsAffected) //返回找到的记录总数
if result.Error != nil {
fmt.Println("update error")
return
}
// 根据 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);
删除
删除一条记录
test := Test{Id: 21}
result := orm.Db.Delete(&test)
fmt.Println(result.RowsAffected) //返回找到的记录总数
if result.Error != nil {
fmt.Println("del error")
return
}
// 带额外条件的删除
db.Where("name = ?", "jinzhu").Delete(&email)
// DELETE from emails where id = 10 AND name = "jinzhu";
根据主键删除
result := orm.Db.Delete(&Test{}, 20)
fmt.Println(result.RowsAffected) //返回找到的记录总数
if result.Error != nil {
fmt.Println("del error")
return
}
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);
批量删除
无主键删除
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%";
逻辑删
删除方法不变,区别在结构体定义
type Test struct {
Id int `json:"id"`
//DeleteTime gorm.DeletedAt `json:"delete_time"` //逻辑删除时将该字段更新为Y-m-d H:i:s
DeleteTime soft_delete.DeletedAt `json:"delete_time"`// 逻辑删除时将该字段更新为时间戳
}
注意,使用 soft_delete.DeletedAt 类型时需要导入 gorm.io/plugin/soft_delete