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, "\r\n", 0))

  

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM