关于golang:聊聊gorm的Transaction

52次阅读

共计 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

正文完
 0