Go框架之GORM学习 | 青训营笔记

72 阅读3分钟

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

Gorm

官方文档:gorm.cn/zh_CN/docs/…

Gorm的默认约定

  • Gorm使用名为ID的字段 作为主键
  • 使用结构体的蛇形负数作为表名,字段名的蛇形作为列名
  • 使用CreatedAt、UpdateAt作为创建、更新时间

1. 定义Gorm Model 和 连接到数据库

1.1 定义Model

gorm.Model

type Model struct {
    ID        uint `gorm:"primarykey"`
    CreatedAt time.Time
    UpdatedAt time.Time
    DeletedAt DeletedAt `gorm:"index"`
}

example:

type Product struct {
   gorm.Model
   Code  string
   Price uint
}

2.1 连接到数据库

dsn := "root:123456@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
   panic("failed to connect database")
}

迁移 ------ AutoMigrate

AutoMigrate 用于自动迁移您的 schema(架构、模式:在数据库系统中是形式语言描述的一种结构,是对象的集合),保持您的 schema 是最新的。

注意: AutoMigrate 会创建表、缺失的外键、约束、列和索引。 如果大小、精度、是否为空可以更改,则 AutoMigrate 会改变列的类型。 出于保护您数据的目的,它 不会 删除未使用的列

db.AutoMigrate(&User{})
db.AutoMigrate(&User{}, &Product{}, &Order{})

2. CURD

users :=make([]*User, 10)

当使用结构体作为条件进行操作时,GORM只会查询非零值字段。如果要以操作零值的话,应该使用Map来进行操作。

  • Create

    可以通过default 标签定义默认值

    	//Create
    	//插入一条数据
    	p := &Product{Code: "D41"}
    	db.Create(p)
    	//插入多条数据
    	products := []*Product{{Code: "D42"}, {Code: "D43"}, {Code: "D44"}}
    	db.Create(products)
    
  • Update

    	//Update
    	//更新单字段
    	db.Model(&User{ID: 111}).Where("age > ?", 18).Update("name", "hello")
    	//更新多个字段(结构体:不更新零值)
    	db.Model(&User{ID: 111}).Updates(User{Name: "hhh", Age: 18})
    	//更新多个字段(map:更新零值)
    	db.Model(&User{ID: 111}).Updates(map[string]interface{}{"name": "hhh", "age": 18})
    	//SQL表达式更新
    	db.Model(&Product{Model: gorm.Model{ID: 111}}).Update("price", gorm.Expr("price * ? + ?", 2, 100))
    
  • Read

    尽量不要使用First

    	//Read
    	db.Where("age > 10").Find(&users)
    	db.Where("name IN ?", []string{"jinzhu", "jinzhu 2"}).Find(&users)
    	db.Where("name LIKE ?", "%jin%").Find(&users)
    	db.Where("name = ? AND age > ?", "jinzhu", "22").Find(&users)
    	db.Where(&User{Name: "jinzhu", Age: 0}).Find(&users)
    	db.Where(map[string]interface{}{"Name": "jinzhu", "Age": 0}).Find(&users)
    
  • Delete

    • GORM提供了gorm.DeletedAt(包含该字段)用于帮助用户实现软删。
    • 拥有软删能力的Model调用Delete时,记录不会被从数据库中真正删除。但GORM会将DeletedAt置为当前时间,并且你不能再通过正常的查询方法找到该记录。
    • 使用Unscoped可以查询到被软删的数据。

    查找被软删的记录:db.Unscoped().Where("age = 20").Find(&users)

    永久删除:db.Unscoped().Delete(&order)

    //Delete
    //删除条件中包含主键
    db.Delete(&p)
    db.Where("name = ?", "jinzhu").Delete(&products)
    db.Delete(&User{}, 10)
    db.Delete(products, []int{1, 2, 3})
    //删除条件中不包含主键,执行批量删除
    db.Where("name like ?", "%y%").Delete(&User{})
    

3. 事务与HOOK

3.1 事务

要在事务中执行一系列操作,一般流程如下:

db.Transaction(func(tx *gorm.DB) error {
   // 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
   if err := tx.Create(&People{Name: "Giraffe"}).Error; err != nil {
      // 返回任何错误都会回滚事务
      return err
   }
   if err := tx.Create(&People{Name: "Lion"}).Error; err != nil {
      return err
   }
   // 返回 nil 提交事务
   return nil
})

3.2 HOOK

  • Hook 是在创建、查询、更新、删除等操作之前、之后调用的函数。
  • 如果您已经为模型定义了指定的方法,它会在创建、更新、查询、删除时自动被调用。如果任何回调返回错误,GORM 将停止后续的操作并回滚事务。
  • 钩子方法的函数签名应该是 func(*gorm.DB) error
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
}
func (u *User) AfterCreate(tx *gorm.DB) (err error) {
}
......

参考链接:

gorm.cn/zh_CN/docs/…