本文次要钻研一下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