以下是《Go语言实战指南》中关于 数据库编程:数据迁移与事务控制 的核心内容,适用于使用 GORM 进行数据库表结构管理与事务性操作。
一、数据迁移(AutoMigrate)
GORM 提供 AutoMigrate() 方法可根据结构体自动创建或更新数据库表结构,适合开发阶段使用。
1. 自动创建表结构
db.AutoMigrate(&User{})
- • 会创建表、缺失字段、索引。
- • 不会删除字段、修改字段类型,所以是“非破坏性迁移”。
- • 多个模型可一并迁移:
db.AutoMigrate(&User{}, &Product{}, &Order{})
2. 常见字段标签
| GORM 标签 | 功能说明 |
primaryKey |
主键 |
uniqueIndex |
唯一索引 |
size:255 |
设置字段长度 |
default:'abc' |
设置默认值 |
not null |
不允许为 NULL |
3. 嵌套字段自动迁移
type Address struct { City string Zip string } type User struct { gorm.Model Name string Address Address `gorm:"embedded"` }
二、事务控制(Transaction)
在实际开发中,涉及多个数据库操作时应使用事务保证一致性。
1. 使用 db.Transaction() 执行事务
err := db.Transaction(func(tx *gorm.DB) error { if err := tx.Create(&User{Name: "Tom"}).Error; err != nil { return err } if err := tx.Create(&Order{UserID: 1, Amount: 100}).Error; err != nil { return err } return nil // 提交事务 }) if err != nil { log.Println("事务失败:", err) }
- • 返回
nil:自动提交。 - • 返回
error:自动回滚。
2. 手动控制事务(更细粒度)
tx := db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() if err := tx.Create(&User{Name: "Alice"}).Error; err != nil { tx.Rollback() return } if err := tx.Create(&Order{UserID: 1}).Error; err != nil { tx.Rollback() return } tx.Commit()
✅ 遇
panic时可通过defer + recover回滚事务,防止程序异常提交。
三、事务的隔离级别(可选配置)
使用 Set 方法可设置隔离级别:
db.Session(&gorm.Session{ Isolation: "REPEATABLE READ", }).Transaction(func(tx *gorm.DB) error { // 操作... return nil })
常见的隔离级别有:
- •
READ UNCOMMITTED - •
READ COMMITTED - •
REPEATABLE READ(MySQL 默认) - •
SERIALIZABLE
四、在 Gin 项目中统一管理事务(实践建议)
如果你使用的是 Gin 框架,可以在中间件中开启事务,将事务对象绑定到 context.Context 中,在业务层统一使用:
// 开启事务中间件 func TransactionMiddleware(db *gorm.DB) gin.HandlerFunc { return func(c *gin.Context) { tx := db.Begin() c.Set("tx", tx) c.Next() if len(c.Errors) > 0 { tx.Rollback() } else { tx.Commit() } } }
业务中获取并使用:
tx := c.MustGet("tx").(*gorm.DB) tx.Create(&User{})
五、小结
| 功能点 | 方法 / 实践 |
| 自动迁移 | db.AutoMigrate(&Model{}) |
| 表结构控制 | 通过 GORM 标签控制字段属性 |
| 简单事务 | db.Transaction(func(tx *gorm.DB) error) |
| 手动事务 | Begin / Commit / Rollback |
| 项目实践 | 中间件中开启事务,绑定到上下文使用 |