gorm框架(二)|青训营笔记

58 阅读2分钟

更新

更新的前提是先查询到记录

Save保存所有字段

用于单个记录的全字段更新

它会保存所有字段,即零值也会保存

var P Person
DB.Take(&P)
P.Age = 23
//全字段更新
DB.Save(&P)

更新指定字段

可以使用select选择要更新的字段

var p Person
DB.Take(&p)
p.Age = 21
//全字段更新
DB.Select("age").Save(&p)

批量更新

例如我想给年龄21的学生,都更新以下邮箱

var PList []Person
DB.Find(&PList,"age = ?",21).Update("email","is21@qq.com")

还要一种更简单的方式

DB.Model(&PList{}).Where("age = ?",21).Update("email","is@qq.com")

这样的更新方式也是可以更新零值的

更新多列

如果是结构体,它默认不会更新零值

email:="xxx@gmail.com"
DB.Model(&Person{}).Where("age = ?",21),Update(Person{
    Email:&email,
    Gender:false,//这个不会更新
})

如果想让他更新零值,用select就好

email:="xxx@qq.com"
DB.Model(&Person{}).Where("age = ?",21).Select("gender","email").Update(Person{
    Email:&email,
    Gender:false,
})

如果不想多写几行代码,推荐使用map

DB.Model(&Person{}).Where("age = ?",21).Update(map[string]any{
    "email":&email,
    "gender":false
})

更新选定字段

Select选定字段 Omit忽略字段

删除

根据结构体删除

db.Delete(&p)

删除多个

db.Delete(&p{},[]int{1,2,3})
db.Delete(&p)

4.创建HOOK

在创建一条记录到数据库的时候,我希望做点事情

type Person struct{
    ID uint `gorm:"size:3"`
    Name string `gorm:"size:8"`
    Age int `gorm:"size:3"`
    Gender bool
    Email *string `gorm:"size:32"`
}
func (user *Person) BeforeCreate(tx *gorm.DB) (err error){
    email:=fmt.Sprintf("%s@qq.com",user.Name)
    user.Email = &email
    return nil
}

5.高级查询

创建表格信息

type PersonName struct {
    ID     uint   `gorm:"size:3"`
    Name   string `gorm:"size:8"`
    Age    int    `gorm:"size:3"`
    Gender bool
    Email  *string `gorm:"size:32"`
}
var Plist []PersonName
    DB.Find(&Plist).Delete(&Plist)
     Plist = []PersonName{
        {1, "小明", 32, true, PtrString("xm@xm.com")},
        {2, "小刘", 33, true, PtrString("xl@xl.com")},
        {3, "小红", 34, false, PtrString("xh@xh.com")},
     }
    DB.Create(&Plist)

Where

//查询姓名为小明的
DB.Where("name = ?", "小明").Find(&Plist)
fmt.Println(Plist)
// //查询姓名不等于小明的
DB.Where("name <> ?", "小明")
fmt.Println(Plist)
// //查询姓名为小明和小刘的
DB.Where("name in ?", []string{"小明", "小刘"}).Find(&Plist)
fmt.Println(Plist)
// //查询姓名为小xx的
DB.Where("name like ?", "小%").Find(&Plist)
fmt.Println(Plist)
// //查询年龄大于23的 邮箱为xx@xm.com的
DB.Where("age > ? ane email like ?", "23", "%@xm.com").Find(&Plist)
fmt.Println(Plist)
// //查询性别为女的 邮箱为xx@xh.com的
DB.Where("gender = ? or email like ?", false, "%@xh.com").Find(&Plist)
fmt.Println(Plist)

使用结构体查询

//会过滤零值
DB.Where(&Person{Name:"小明",Age:33}).Find(&Plist)
fmt.Println(Plist)

使用map查询

不会过滤零值

DB.Where(map[string]any{"name": "小刘", "age": 33}).Find(&Plist)
fmt.Println(Plist)

Not条件

和Where中的not等价

DB.Not("age > 23").Find(&Plist)
fmt.Println(Plist)

Or条件

和Where中的or等价

DB.Or("gender = ?",false).Or("email like ?","xx@xm.com").Find(&Plist)

Select选择字段

DB.Select("name","age").Find(&Plist)
fmt.Println(Plist)
//没有被选中,会被赋零值

可以使用扫描Scan,讲选择的字段存入另一个结构体中

type User struct{
    Name string
    Age int
}
var persons []Person
var users []User
DB.Select("name","age").Find(&persons).Scan(&users)
fmt.Println(users)

这样写也是可以的,不过最终会查询两次,还是不这样写

SELECT `name`,`ago` FROM `students`
SELECT `name`,`ago` FROM `students`

这样写就只查询一次了

type User struct{
    Name string
    Age int
}
var persons []Person
var users []User
DB.Model("name","age").Find(&persons).Scan(&users)
fmt.Println(users)

还可以这样

var users []User
DB.Table("persons"),Select("name","ago"),Scan(&Plist)
fmt.Println(users)

Scan是根据column列名进行扫描的