🏆 事务

⭐️ 在 GORM 中,事务(Transaction)是一种数据库操作机制,它允许你在一个单独的操作单元内执行一系列的数据库操作,并且要么全部成功提交(commit),要么全部失败回滚(rollback)。这种机制确保了在复杂的数据库操作中数据的一致性和完整性。

🍅 禁用事务

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

🍅 执行事务

官网示列

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
})

自己编写


//Many to Many创建关系
u1 := &User{
    Name:     "tanc",
    Password: "1234567",
    Tasks: []Task{
        {Title: "JavaWeb大作业"},
        {Title: "安卓大作业"},
        {Title: "web大作业"},
    },
}

//设置一个事务,使他失败
err = db.Transaction(func(tx *gorm.DB) error {
    create := tx.Create(u1)
    if create.Error != nil {
        fmt.Println("创建失败")
        return create.Error
    }

    var tasks Task
    tx.Model(&u1).Association("Tasks").Find(&tasks)
    fmt.Println("事务失败前: ", tasks)

    return errors.New("手动失败")
})
if err != nil {
    fmt.Println("事务失败", err.Error())
}

var tasks Task
db.Model(&u1).Association("Tasks").Find(&tasks)
fmt.Println("事务失败后: ", tasks)


//输出:
C:\Users\tanchang\AppData\Local\JetBrains\GoLand2023.3\tmp\GoLand\___1go_build_GORM_STU_GORM_Connect.exe
事务失败前:  {{1 2024-07-03 17:49:39.977 +0800 CST 2024-07-03 17:49:39.977 +0800
 CST {0001-01-01 00:00:00 +0000 UTC false}} JavaWeb大作业 []}

事务失败 手动失败

事务失败后:  {{0 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC {00
01-01-01 00:00:00 +0000 UTC false}}  []}

🍵 嵌套事务

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

err = db.Transaction(func(tx *gorm.DB) error {
    err2 := db.Transaction(func(tx *gorm.DB) error {
        create := tx.Create(u1)
        if create.Error != nil {
            fmt.Println("创建失败")
            return errors.New("创建用户失败 回滚")
        }
        return nil
    })
    if err2 != nil {
        fmt.Println("事务失败", err2.Error())
        return err2
    }

    var tasks Task
    tx.Model(&u1).Association("Tasks").Find(&tasks)
    fmt.Println("事务失败前: ", tasks)

    return errors.New("手动失败")
})

🍅 手动事务

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

// 开始事务
tx := db.Begin()

// 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
tx.Create(...)

// ...

// 遇到错误时回滚事务
tx.Rollback()

// 否则,提交事务
tx.Commit()
//设置一个事务,使他失败
tx := db.Begin()
tx.Create(u1)

var tasks1 Task
tx.Model(&u1).Association("Tasks").Find(&tasks1)
fmt.Println("事务失败前: ", tasks1)

tx.Rollback()

tx.Commit()

var tasks2 Task
db.Model(&u1).Association("Tasks").Find(&tasks2)
fmt.Println("事务失败后: ", tasks2)

🍅 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