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"`
}
自动事务

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

func Transaction() {
	t := Teacher{
		Name:   "yuan",
		Age:    41,
		Salary: 122345.123,
		Email:  "[email protected]",
	}
	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
	})
}
嵌套事务

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

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

func NestTransaction() {
	t := Teacher{
		Name:   "yuan",
		Age:    41,
		Salary: 122345.123,
		Email:  "[email protected]",
	}
	t1 := Teacher{
		Name:   "yuan2",
		Age:    40,
		Salary: 12345.123,
		Email:  "[email protected]",,
	}
	t2 := Teacher{
		Name:   "yuan3",
		Age:    50,
		Salary: 12345.123,
		Email:  "[email protected]",,
	}
	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
	})
}
手动事务

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

func ManualTransaction() {
	t := Teacher{
		Name:   "yuan",
		Age:    41,
		Salary: 122345.123,
		Email:  "[email protected]",
	}
	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()
}
检查点savePoint

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

func SavePointTransaction() {
	t := Teacher{
		Name:   "yuan",
		Age:    41,
		Salary: 122345.123,
		Email:  "[email protected]",
	}
	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()
}

你可能感兴趣的:(golang,数据库,开发语言)