• Gorm的高级用法


      一、 钩子

      钩子是一个在 插入 / 查询 / 更新 / 删除 之前或之后被调用的方法。

      在一个模型中定义特殊的方法,它将会在插入,更新,查询,删除的时候被自动调用,如果任何的回调抛出错误,GORM 将会停止将要执行的操作并且回滚当前的改变。

    // 开启事务
    BeforeSave
    BeforeCreate
    // 连表前的保存
    // 更新时间戳 `CreatedAt`, `UpdatedAt`
    // 保存自己
    // 重载哪些有默认值和空的字段
    // 链表后的保存
    AfterCreate
    AfterSave
    // 提交或回滚事务
    

      Example:

    func (u *User) BeforeSave() (err error) {
        if u.IsValid() {
            err = errors.New("can't save invalid data")
        }
        return
    }
    
    func (u *User) AfterCreate(scope *gorm.Scope) (err error) {
        if u.ID == 1 {
        scope.DB().Model(u).Update("role", "admin")
      }
        return
    }
    
    //   在 GORM 中的保存 / 删除 操作会默认进行事务处理,所以在事物中,所有的改变都是无效的,直到它被提交为止:
    func (u *User) AfterCreate(tx *gorm.DB) (err error) {
        tx.Model(u).Update("role", "admin")
        return
    }
    

      更新对象

    // 开启事务
    BeforeSave
    BeforeUpdate
    // 链表前的保存
    // 更新时间戳 `UpdatedAt`
    // 保存自身
    // 链表后的保存
    AfterUpdate
    AfterSave
    // 提交或回滚的事务
    
    func (u *User) BeforeUpdate() (err error) {
        if u.readonly() {
            err = errors.New("read only user")
        }
        return
    }
    
    // 在事务结束后,进行更新数据
    func (u *User) AfterUpdate(tx *gorm.DB) (err error) {
      if u.Confirmed {
        tx.Model(&Address{}).Where("user_id = ?", u.ID).Update("verfied", true)
      }
        return
    }
    

      删除对象:可用于删除的钩子

    // 开启事务
    BeforeDelete
    // 删除自身
    AfterDelete
    // 提交或回滚事务
    
    
    // 在事务结束后进行更新数据
    func (u *User) AfterDelete(tx *gorm.DB) (err error) {
      if u.Confirmed {
        tx.Model(&Address{}).Where("user_id = ?", u.ID).Update("invalid", false)
      }
        return
    }
    

      查询对象:可用于查询的钩子

    // 从数据库中读取数据
    // 加载之前 (急于加载)
    AfterFind
    
    func (u *User) AfterFind() (err error) {
      if u.MemberShip == "" {
        u.MemberShip = "user"
      }
        return
    }
    

     二、事务

                     GORM 默认在事务中执行单个 create, update, delete 操作,以确保数据库数据完整性。如果需要将多个 create, update, delete 当成一个原子性操作,Transaction 就是为了这个而创造的。

           事务流程:

    // 开启事务
    tx := db.Begin()
    
    // 在事务中执行一些数据库操作 (从这里开始使用 'tx',而不是 'db')
    tx.Create(...)
    
    // ...
    
    // 发生错误回滚事务
    tx.Rollback()
    
    // 或者提交这个事务
    tx.Commit()
    

      

        三、运行原生SQL

      执行原生SQL时不能使用链式调用其他方法

    db.Exec("DROP TABLE users;")
    db.Exec("UPDATE orders SET shipped_at=? WHERE id IN (?)", time.Now(), []int64{11,22,33})
    
    // Scan
    type Result struct {
        Name string
        Age  int
    }
    
    var result Result
    db.Raw("SELECT name, age FROM users WHERE name = ?", 3).Scan(&result)
    

      使用 *sql.Row 或者 *sql.Rows 获得查询结果

    row := db.Table("users").Where("name = ?", "jinzhu").Select("name, age").Row() // (*sql.Row)
    row.Scan(&name, &age)
    
    rows, err := db.Model(&User{}).Where("name = ?", "jinzhu").Select("name, age, email").Rows() // (*sql.Rows, error)
    defer rows.Close()
    for rows.Next() {
        ...
        rows.Scan(&name, &age, &email)
        ...
    }
    
    // 原生SQL
    rows, err := db.Raw("select name, age, email from users where name = ?", "jinzhu").Rows() // (*sql.Rows, error)
    defer rows.Close()
    for rows.Next() {
        ...
        rows.Scan(&name, &age, &email)
        ...
    }   

           扫描 sql.Rows 数据到模型

    rows, err := db.Model(&User{}).Where("name = ?", "jinzhu").Select("name, age, email").Rows() // (*sql.Rows, error)
    defer rows.Close()
    
    for rows.Next() {
      var user User
      // ScanRows 扫描一行到 user 模型
      db.ScanRows(rows, &user)
    
      // do something
    }
    

     四、数据库接口

         GORM 提供了从当前的 *gorm.DB 连接中返回通用的数据库接口的方法 DB *sql.DB 。

    // 获取通用数据库对象 sql.DB 来使用他的 db.DB() 方法
    
    // Ping
    db.DB().Ping()
    
    //   连接池
    
    // SetMaxIdleConns 设置空闲连接池中的最大连接数。
    db.DB().SetMaxIdleConns(10)
    
    // SetMaxOpenConns 设置数据库连接最大打开数。
    db.DB().SetMaxOpenConns(100)
    
    // SetConnMaxLifetime 设置可重用连接的最长时间
    db.DB().SetConnMaxLifetime(time.Hour)
    

     五、自定义Loggor(感觉没啥用)

    // 开启 Logger, 以展示详细的日志
    db.LogMode(true)
    
    // 关闭 Logger, 不再展示任何日志,即使是错误日志
    db.LogMode(false)
    
    // 对某个操作展示详细的日志,用来排查该操作的问题
    db.Debug().Where("name = ?", "jinzhu").First(&User{})
    

    参考 GORM 的默认 logger 是怎么自定义的 github.com/jinzhu/gorm/blob/master...

    例如,使用  Revel 的 Logger 作为 GORM 的输出

    db.SetLogger(gorm.Logger{revel.TRACE})
    
    // 使用 os.Stdout 作为输出
    db.SetLogger(log.New(os.Stdout, "
    ", 0))
    

      

      

  • 相关阅读:
    帮Netpole Review了一下RichEditor控件
    WawaKMv1命名空间.rtf
    WawaKMV1需求变更.rtf
    WawaKMV1技术难点.rtf
    WawaKMV1工具栏设计.rtf
    通讯录相关需求分析
    WawaKMV1Urtal Recall分析.rtf
    WawaKM:关于批量抓图的需求分析及设计
    图片相关的需求分析
    蛙蛙郑重推荐您使用firefox浏览器
  • 原文地址:https://www.cnblogs.com/lvpengbo/p/13705913.html
Copyright © 2020-2023  润新知