gorm 事务的使用

本文涉及的产品
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
简介: 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()
}


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
8月前
|
算法 Go
Go 语言泛型 — 泛型语法与示例
本文详解 Go 语言泛型语法与使用示例,涵盖泛型函数、类型声明、类型约束及实战应用,适合入门学习与开发实践。
|
9月前
|
SQL 数据库连接 Go
Go语言数据库编程:GORM 的基本使用
GORM 是 Go 语言最流行的 ORM 框架,封装了 database/sql,支持自动迁移、关联关系、事务等功能,开发体验接近高层语言的 ORM。本文介绍了 GORM 的安装与初始化、模型定义、自动迁移、基本 CRUD 操作、条件构造器、钩子函数、事务处理、日志调试等内容,帮助开发者快速掌握其使用方法。
|
10月前
|
SQL Go 数据库
Gorm使用教程:掌握高级查询的技巧。
以上就是我们今天的旅程中所会遇到的一些有趣的Gorm查询技巧。学习这些技巧像是学着驾驶一辆全新的巴士,只要你掌握了这些,你可以在数据库的海洋中自由驾驶,轻松地转向,畅游其中。祝你在Gorm的世界中探索愉快!
272 36
|
8月前
|
存储 人工智能 安全
深入理解 go sync.Map - 基本原理
本文介绍了 Go 语言中 `map` 在并发使用时的常见问题及其解决方案,重点对比了 `sync.Mutex`、`sync.RWMutex` 和 `sync.Map` 的性能差异及适用场景。文章指出,普通 `map` 不支持并发读写,容易引发错误;而 `sync.Map` 通过原子操作和优化设计,在某些场景下能显著提升性能。同时详细讲解了 `sync.Map` 的基本用法及其适合的应用环境,如读多写少或不同 goroutine 操作不同键的场景。
389 1
|
人工智能 自然语言处理 搜索推荐
GLM-Realtime:智谱推出多模态交互AI模型,融入清唱功能,支持视频和语音交互
GLM-Realtime 是智谱推出的端到端多模态模型,具备低延迟的视频理解与语音交互能力,支持清唱功能、2分钟内容记忆及灵活调用外部工具,适用于多种智能场景。
706 4
GLM-Realtime:智谱推出多模态交互AI模型,融入清唱功能,支持视频和语音交互
|
缓存 监控 前端开发
Go 语言中如何集成 WebSocket 与 Socket.IO,实现高效、灵活的实时通信
本文探讨了在 Go 语言中如何集成 WebSocket 与 Socket.IO,实现高效、灵活的实时通信。首先介绍了 WebSocket 和 Socket.IO 的基本概念及其优势,接着详细讲解了 Go 语言中 WebSocket 的实现方法,以及二者集成的重要意义和具体步骤。文章还讨论了集成过程中需要注意的问题,如协议兼容性、消息格式、并发处理等,并提供了实时聊天、数据监控和在线协作工具等应用案例,最后提出了性能优化策略,包括数据压缩、缓存策略和连接管理优化。旨在帮助开发者更好地理解并应用这些技术。
878 3
|
JSON 数据库 数据格式
gorm 教程三 gen自动代码生成工具
gorm 教程三 gen自动代码生成工具
1318 0
|
存储 Java 数据处理
DO/SDO/DTO/VO 都是什么
【5月更文挑战第7天】DO/SDO/DTO/VO 都是什么
512 2
|
JSON 前端开发 数据格式
`java.time.LocalDateTime` from String \“2020-11-19\“: Failed to deserialize java.time.LocalDateTime
`java.time.LocalDateTime` from String \“2020-11-19\“: Failed to deserialize java.time.LocalDateTime
374 1

热门文章

最新文章