1月28日Go学习笔记|青训营笔记

76 阅读2分钟

这是我参与【第五届青训营】伴学笔记创作活动的第六天

Gorm-事务

为了确定数据库的完整性([[数据库基本概念#数据库完整性]]),对数据库的原子操作,需要被事务包裹,方便出错时进行回滚,

禁用默认事务

为了确保数据一致性,GORM 会在事务里执行写入操作(创建、更新、删除)。如果没有这方面的要求,可以在初始化时禁用它,这将获得大约 30%+ 性能提升。

// 全局禁用  
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{  
  SkipDefaultTransaction: true,  //关闭默认事务
})  
  
// 持续会话模式  
tx := db.Session(&Session{SkipDefaultTransaction: true})  
tx.First(&user, 1)  
tx.Find(&users)  
tx.Model(&user).Update("Age", 18)  

事务

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

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

嵌套事务

GORM 支持嵌套事务,您可以回滚较大事务内执行的一部分操作,例如:

db.Transaction(func(tx *gorm.DB) error {  
  tx.Create(&user1)  
  
  tx.Transaction(func(tx2 *gorm.DB) error {  
    tx2.Create(&user2)  
    return errors.New("rollback user2") // Rollback user2  
  })  
  
  tx.Transaction(func(tx2 *gorm.DB) error {  
    tx2.Create(&user3)  
    return nil  
  })  
  
  return nil  
})  
  
// Commit user1, user3  

手动事务

Gorm 支持直接调用事务控制方法(commit、rollback),例如:

// 开始事务  
tx := db.Begin()  
  
// 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')  
tx.Create(...)  
  
// ...  
  
// 遇到错误时回滚事务  
tx.Rollback()  
  
// 否则,提交事务  
tx.Commit()  

一个特殊的示例

func CreateAnimals(db *gorm.DB) error {  
  // 再唠叨一下,事务一旦开始,你就应该使用 tx 处理数据  
  tx := db.Begin()  
  defer func() {  
    if r := recover(); r != nil {  
      tx.Rollback()  
    }  
  }()  
  
  if err := tx.Error; err != nil {  
    return err  
  }  
  
  if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {  
     tx.Rollback()  
     return err  
  }  
  
  if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {  
     tx.Rollback()  
     return err  
  }  
  
  return tx.Commit().Error  
}  

SavePoint、RollbackTo

GORM 提供了 SavePointRollbackto 方法,来提供保存点以及回滚至保存点功能,例如:

tx := db.Begin()  
tx.Create(&user1)  
  
tx.SavePoint("sp1")  
tx.Create(&user2)  
tx.RollbackTo("sp1") // Rollback user2  
  
tx.Commit() // Commit user1