共计 1414 个字符,预计需要花费 4 分钟才能阅读完成。
序
本文次要钻研一下 gorm 的 Transaction
Transaction
gorm.io/gorm@v1.20.10/finisher_api.go
// Transaction start a transaction as a block, return error will rollback, otherwise to commit.
func (db *DB) Transaction(fc func(tx *DB) error, opts ...*sql.TxOptions) (err error) {
panicked := true
if committer, ok := db.Statement.ConnPool.(TxCommitter); ok && committer != nil {
// nested transaction
if !db.DisableNestedTransaction {err = db.SavePoint(fmt.Sprintf("sp%p", fc)).Error
defer func() {
// Make sure to rollback when panic, Block error or Commit error
if panicked || err != nil {db.RollbackTo(fmt.Sprintf("sp%p", fc))
}
}()}
if err == nil {err = fc(db.Session(&Session{}))
}
} else {tx := db.Begin(opts...)
defer func() {
// Make sure to rollback when panic, Block error or Commit error
if panicked || err != nil {tx.Rollback()
}
}()
if err = tx.Error; err == nil {err = fc(tx)
}
if err == nil {err = tx.Commit().Error
}
}
panicked = false
return
}
DB 的 Transaction 办法针对非 TxCommitter 类型的 db.Statement.ConnPool 执行 db.Begin,之后注册 defer 针对 panicked 或者 err 的执行 tx.Rollback(),执行 fc 之后,判断 err 为 nil 的状况下执行 tx.Commit(),并将 Error 赋值为 err
实例
func TestInsertInTx(t *testing.T) {err := db.Transaction(func(tx *gorm.DB) error {classes := []model.Class{
{Name: "abc2",},
{Name: "abc2",},
}
err := db.Create(&classes).Error
if err != nil {return err}
uc := []model.UserClass{
{
UserId: 1,
ClassId: classes[0].ID,
},
{
UserId: 1,
ClassId: classes[1].ID,
},
}
err2 := db.Create(&uc).Error
if err2 != nil {return err2}
return nil
})
if err != nil {t.Error(err)
}
}
小结
gorm 的 DB 提供了 Transaction 办法,相当于一个事务模板,主动 commit 或者 rollback,它提供了 func(tx *gorm.DB) error 参数用于自定义事务内的数据库操作。
doc
- gorm
正文完