gorm 事务的使用

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: gorm 事务的使用

gorm事务默认是开启的。为了确保数据一致性,GORM 会在事务里执行写入操作(创建、更新、删除)。

如果没有这方面的要求,您可以在初始化时禁用它,这将获得大约 30%+ 性能提升。

一般不推荐禁用

// 全局禁用
db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{
  SkipDefaultTransaction: true,
})

普通事务

type TMG struct {
  ID   uint
  Name string
}
func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&TMG{})
  db.Transaction(func(tx *gorm.DB) error {
    // 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
    if err := tx.Create(&TMG{Name: "Giraffe"}).Error; err != nil {
      // 返回任何错误都会回滚事务
      return err
    }
    if err := tx.Create(&TMG{Name: "Lion"}).Error; err != nil {
      return err
    }
    // 返回 nil 提交事务
    return nil
  })
}

执行下面代码,其中执行返回了一个test for err的错误,此时事务自动回滚,数据表中无数据

type TMG struct {
  ID   uint
  Name string
}
func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&TMG{})
  flag := false
  err := db.Transaction(func(tx *gorm.DB) error {
    // 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
    if err := tx.Create(&TMG{Name: "Giraffe"}).Error; err != nil {
      // 返回任何错误都会回滚事务
      return err
    }
    if !flag {
      return errors.New("test for err")
    }
    if err := tx.Create(&TMG{Name: "Lion"}).Error; err != nil {
      return err
    }
    // 返回 nil 提交事务
    return nil
  })
  if err != nil {
    fmt.Println(err)//test for err
  }
}

嵌套事务

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

在下面代码中,我们知道包含name2的事务返回了err,是会回滚的,而外层事务返回nil,则会提交

func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&TMG{})
  db.Transaction(func(tx *gorm.DB) error {
    tx.Create(&TMG{Name: "name 1"})
    tx.Transaction(func(tx2 *gorm.DB) error {
      tx2.Create(&TMG{Name: "name 2"})
      return errors.New("rollback user2") // Rollback user2
    })
    tx.Transaction(func(tx2 *gorm.DB) error {
      tx2.Create(&TMG{Name: "name 3"})
      return nil
    })
    return nil
  })
}


手动事务

func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&TMG{})
  // 开始事务
  tx := db.Begin()
  // 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
  tx.Create(&TMG{Name: "wxf1"})
  tx.Create(&TMG{Name: "wxf2"})
  tx.Create(&TMG{Name: "wxf3"})
  // ...
  ...
  if err!=nil{
    // 遇到错误时回滚事务
    fmt.Println(tx.Rollback().Error)
  }
  ...
  // 否则,提交事务
  fmt.Println(tx.Commit().Error)
}

一个特殊的示例

type TMG struct {
  ID   uint
  Name string
}
func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&TMG{})
  // 事务
  CreateTMG(db)
}
func CreateTMG(db *gorm.DB) error {
  // 再唠叨一下,事务一旦开始,你就应该使用 tx 处理数据
  tx := db.Begin()
  defer func() {
    if r := recover(); r != nil {
      tx.Rollback()
    }
  }()
  if err := tx.Error; err != nil {
    return err
  }
  if err := tx.Create(&TMG{Name: "Giraffe"}).Error; err != nil {
    tx.Rollback()
    return err
  }
  if err := tx.Create(&TMG{Name: "Lion"}).Error; err != nil {
    tx.Rollback()
    return err
  }
  return tx.Commit().Error
}

SavePoint、RollbackTo

GORM 提供了 SavePoint、Rollbackto 方法,来提供保存点以及回滚至保存点功能

这里rollback到了sp1的位置,也就是说,数据库中只存了wxf666这条数据

func main() {
  db, _ := gorm.Open(mysql.New(mysql.Config{DSN: "root:123456@tcp(127.0.0.1:3306)/gormDB?charset=utf8mb4&parseTime=True&loc=Local"}), &gorm.Config{})
  db.AutoMigrate(&TMG{})
  // 事务
  tx := db.Begin()
  tx.Create(&TMG{Name: "wxf666"})
  tx.SavePoint("sp1")
  tx.Create(&TMG{Name: "wxf777"})
  tx.Create(&TMG{Name: "wxf888"})
  tx.SavePoint("sp2")
  tx.RollbackTo("sp1")
  tx.Commit()
}


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3天前
|
SQL 数据库 索引
gorm普通的增删改查
gorm普通的增删改查
33 0
|
3天前
|
SQL 数据库
GORM—增
GORM—增
28 0
|
7月前
|
SQL 安全 数据库
GORM V2 写操作
GORM V2 写操作
31 0
|
7月前
|
关系型数据库 MySQL 数据库
GORM V2 读操作
GORM V2 读操作
24 1
|
11月前
|
SQL
GORM中使用事务
GORM中使用事务
90 0
|
12月前
|
SQL Java 数据库连接
事务介绍、JDBC中对事务的处理及事务的ACID属性
事务介绍、JDBC中对事务的处理及事务的ACID属性
66 0
|
数据安全/隐私保护
简单的GORM使用
简单的GORM使用 1.安装 2.字段级权限控制 3.CRUD Create Retrieve Update Delete 4.事务
104 0
|
Go
GORM v2 一对一关联查询使用(Belongs To 、Has One)
GORM v2 一对一关联查询使用(Belongs To 、Has One)
353 0
GORM v2 一对一关联查询使用(Belongs To 、Has One)
|
SQL
gorm批量插入解决方案
gorm批量插入解决方案
929 0
gorm批量插入解决方案
|
SQL 关系型数据库 MySQL
【GORM】使用GORM连接各种数据库
1.概述 gorm是一个使用Go语言编写的ORM框架。它文档齐全,对开发者友好,支持主流数据库。
836 0