美文网首页
聊聊gorm的Transaction

聊聊gorm的Transaction

作者: go4it | 来源:发表于2021-01-12 23:54 被阅读0次

    本文主要研究一下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的Transaction

          本文链接:https://www.haomeiwen.com/subject/ntpyaktx.html