• golang gorm —— 事务、回滚、savepoint


    gorm事务

    model定义

    type Roles []string
    
    type Teacher struct {
        gorm.Model
        Name     string   `gorm:"size:256"`
        Email    string   `gorm:"size:256"`
        Salary   float64  `gorm:"scale:2;precision:7"`   // 指定小数部分宽度为2,列宽度为7. 列宽:【整数部分+小数部分的总长度】【不含小数点】
        Age      uint8    `gorm:"check:age>30"`
        Birthday int64    `gorm:"serializer:unixtime;type:time"`  // 反序列化方式 unixtime, 类型为time
        Roles    Roles    `gorm:"serializer:json"`
        JobInfo  Job      `gorm:"embedded;embeddedPrefix:job_"`   // 嵌套字段, 嵌入字段的列名前缀job_
        JobInfo2 Job      `gorm:"type:bytes;serializer:gob"`      // 字节流类型,gob反序列化,go自己的序列化方法,跨语言项目的时候,不建议用
    }
    
    type Job struct {
        Title    string
        Location string
    }
    
    type Course struct {
        gorm.Model
        Name   string  `gorm:"size:256"`
        Price  float64 `gorm:"scale:2;precision:7"`
        UserID uint    `gorm:"type:int"`
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    自动事务

    gorm提供了自动事务的机制,不需要我们手动提交和回滚

    func Transaction() {
    	t := Teacher{
    		Name:   "yuan",
    		Age:    41,
    		Salary: 122345.123,
    		Email:  "yuan@test.com",
    	}
    	c := Course{
    		Name:  "golang",
    		Price: 12345.1234,
    	}
    	DB.Transaction(func(tx *gorm.DB) error {
    		if err := tx.Create(&t).Error; err != nil {
                // 返回err 会自动回滚事务
    			return err
    		}
    		c.UserID = t.ID
    		if err := tx.Create(&c).Error; err != nil {
    			return err
    		}
            // 返回nil 则提交事务
    		return nil
    	})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    嵌套事务

    gorm事务可以嵌套,大事务里嵌套小事务,只有大事务成功提交,必须大事务提交成功,内部嵌套的事务才能提交成功。如果失败了,可以回滚嵌套的事务。

    注意:嵌套事务不应在gorm中大量使用,因为其不支持预编译

    func NestTransaction() {
    	t := Teacher{
    		Name:   "yuan",
    		Age:    41,
    		Salary: 122345.123,
    		Email:  "yuan@test.com",
    	}
    	t1 := Teacher{
    		Name:   "yuan2",
    		Age:    40,
    		Salary: 12345.123,
    		Email:  "yuan@test.com",,
    	}
    	t2 := Teacher{
    		Name:   "yuan3",
    		Age:    50,
    		Salary: 12345.123,
    		Email:  "yuan@test.com",,
    	}
    	DB.Transaction(func(tx *gorm.DB) error {
    		if err := tx.Create(&t).Error; err != nil {
    			return err
    		}
    		tx.Transaction(func(tx1 *gorm.DB) error {
    			if err := tx1.Create(&t1).Error; err != nil {
    				return err
    			}
    			return nil
    		})
    		tx.Transaction(func(tx1 *gorm.DB) error {
    			if err := tx1.Create(&t2).Error; err != nil {
    				return err
    			}
    			return nil
    		})
    		return nil
    	})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    手动事务

    gorm也提供了begin, rollback等接口支持手动事务的操作

    func ManualTransaction() {
    	t := Teacher{
    		Name:   "yuan",
    		Age:    41,
    		Salary: 122345.123,
    		Email:  "yuan@test.com",
    	}
    	c := Course{
    		Name:  "golang",
    		Price: 12345.1234,
    	}
    
    	tx := DB.Begin()
    	defer func() {
    		if err := recover(); err != nil {
    			tx.Rollback()
    		}
    	}()
    	if tx.Error != nil {
    		log.Fatal(tx.Error)
    		return
    	}
    
    	if err := tx.Create(&t).Error; err != nil {
    		tx.Rollback()
    		return
    	}
    	c.UserID = t.ID
    	if err := tx.Create(&c).Error; err != nil {
    		tx.Rollback()
    		return
    	}
    	tx.Commit()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    检查点savePoint

    gorm也提供了savePoint的机制来支持事务的分段提交,回滚到某个特定的savePoint(RollbackTo)

    func SavePointTransaction() {
    	t := Teacher{
    		Name:   "yuan",
    		Age:    41,
    		Salary: 122345.123,
    		Email:  "yuan@test.com",
    	}
    	c := Course{
    		Name:  "golang",
    		Price: 12345.1234,
    	}
    
    	tx := DB.Begin()
    	defer func() {
    		if err := recover(); err != nil {
    			tx.Rollback()
    		}
    	}()
    	if tx.Error != nil {
    		log.Fatal(tx.Error)
    		return
    	}
    
    	if err := tx.Create(&t).Error; err != nil {
    		tx.Rollback()
    		return
    	}
        // 创建savepoint
    	tx.SavePoint("teacher")
    	c.UserID = t.ID
    	if err := tx.Create(&c).Error; err != nil {
            // 回滚到对应savepoint
    		tx.RollbackTo("teacher")
    		return
    	}
    	tx.Commit()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
  • 相关阅读:
    介绍VMware通过电脑本机网卡链接外部网络
    【EC200U】 SIM卡使用
    小程序实现人脸识别功能
    解决Visio和office365安装兼容问题
    k8s~ingress_service_endpoint_pod四壮士
    阿里云宣布核心产品全面 Serverless 化
    微服务面试必读:拆分、事务、设计的综合解析与实践指南
    6187. 完成所有交易的初始最少钱数(每日一难phase2--day19)
    再谈Rocket MQ消费进度问题
    2023年第十六届山东省职业院校技能大赛中职组“网络安全”赛项规程
  • 原文地址:https://blog.csdn.net/qq_43058348/article/details/133740394