以下是《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 |
项目实践 | 中间件中开启事务,绑定到上下文使用 |