乐闻世界logo
搜索文章和话题

GORM 的 AutoMigrate 功能如何使用?

3月6日 21:37

GORM 的自动迁移功能可以自动创建、更新数据库表结构,使数据库 schema 与 Go 结构体保持同步。

AutoMigrate 基本用法

基本迁移

go
// 自动迁移 User 模型 db.AutoMigrate(&User{}) // 迁移多个模型 db.AutoMigrate(&User{}, &Profile{}, &Order{}) // 迁移所有模型 db.AutoMigrate( &User{}, &Profile{}, &Order{}, &Product{}, )

模型定义和标签

基本模型

go
type User struct { ID uint `gorm:"primaryKey"` Name string `gorm:"size:100;not null"` Email string `gorm:"size:100;uniqueIndex"` Age int `gorm:"default:0"` CreatedAt time.Time `gorm:"autoCreateTime"` UpdatedAt time.Time `gorm:"autoUpdateTime"` DeletedAt gorm.DeletedAt `gorm:"index"` }

使用 gorm.Model

go
type User struct { gorm.Model Name string `gorm:"size:100;not null"` Email string `gorm:"size:100;uniqueIndex"` }

常用标签

主键

go
ID uint `gorm:"primaryKey"`

字段类型

go
Name string `gorm:"type:varchar(100)"` Age int `gorm:"type:tinyint"` Price float64 `gorm:"type:decimal(10,2)"`

字段大小

go
Name string `gorm:"size:100"`

默认值

go
Age int `gorm:"default:0"` Status string `gorm:"default:'active'"`

非空约束

go
Name string `gorm:"not null"`

唯一索引

go
Email string `gorm:"unique"` Email string `gorm:"uniqueIndex"`

普通索引

go
Name string `gorm:"index"` Name string `gorm:"index:idx_name"`

复合索引

go
type User struct { Name string `gorm:"index:idx_name_age"` Age int `gorm:"index:idx_name_age"` }

自定义表名

go
type User struct { gorm.Model Name string } func (User) TableName() string { return "sys_users" }

忽略字段

go
type User struct { Name string Password string `gorm:"-"` TempField string `gorm:"-"` }

高级迁移功能

添加外键

go
type Profile struct { gorm.Model UserID uint `gorm:"not null;index"` User User `gorm:"foreignKey:UserID;references:ID"` Bio string }

多对多关系

go
type User struct { gorm.Model Roles []Role `gorm:"many2many:user_roles;"` } type Role struct { gorm.Model Name string Users []User `gorm:"many2many:user_roles;"` }

嵌入结构体

go
type BaseModel struct { ID uint `gorm:"primaryKey"` CreatedAt time.Time `gorm:"autoCreateTime"` UpdatedAt time.Time `gorm:"autoUpdateTime"` } type User struct { BaseModel Name string }

迁移限制

AutoMigrate 不会做的事情

  • 不会删除列
  • 不会重命名列
  • 不会删除表
  • 不会修改列类型(可能导致数据丢失)

手动处理复杂变更

go
// 添加列 db.Migrator().AddColumn(&User{}, "NewField") // 删除列 db.Migrator().DropColumn(&User{}, "OldField") // 重命名列 db.Migrator().RenameColumn(&User{}, "OldName", "NewName") // 添加索引 db.Migrator().CreateIndex(&User{}, "Email") // 删除索引 db.Migrator().DropIndex(&User{}, "Email") // 重命名索引 db.Migrator().RenameIndex(&User{}, "OldIndex", "NewIndex") // 检查表是否存在 hasTable := db.Migrator().HasTable(&User{}) // 删除表 db.Migrator().DropTable(&User{}) // 重命名表 db.Migrator().RenameTable("old_users", "new_users")

迁移最佳实践

1. 版本控制

go
type Migration struct { ID uint `gorm:"primaryKey"` Name string `gorm:"unique"` AppliedAt time.Time `gorm:"autoCreateTime"` } func RunMigrations(db *gorm.DB) error { // 迁移表结构 if err := db.AutoMigrate(&User{}, &Profile{}); err != nil { return err } // 迁移数据 migrations := []string{ "add_email_index", "update_user_status", } for _, migration := range migrations { var count int64 db.Model(&Migration{}).Where("name = ?", migration).Count(&count) if count > 0 { continue } if err := applyMigration(db, migration); err != nil { return err } db.Create(&Migration{Name: migration}) } return nil }

2. 数据迁移

go
func migrateUserData(db *gorm.DB) error { return db.Transaction(func(tx *gorm.DB) error { var users []User if err := tx.Find(&users).Error; err != nil { return err } for _, user := range users { if user.Status == "" { user.Status = "active" if err := tx.Save(&user).Error; err != nil { return err } } } return nil }) }

3. 回滚机制

go
type Migration struct { Name string Up func(*gorm.DB) error Down func(*gorm.DB) error } var migrations = []Migration{ { Name: "add_email_field", Up: func(db *gorm.DB) error { return db.Migrator().AddColumn(&User{}, "Email") }, Down: func(db *gorm.DB) error { return db.Migrator().DropColumn(&User{}, "Email") }, }, }

注意事项

  1. 生产环境谨慎:在生产环境中使用 AutoMigrate 要非常谨慎,建议先在测试环境验证
  2. 数据备份:执行迁移前务必备份数据
  3. 版本控制:将迁移脚本纳入版本控制
  4. 测试覆盖:为迁移逻辑编写充分的测试
  5. 性能考虑:大型表的迁移可能需要较长时间,考虑分批处理
  6. 兼容性:注意不同数据库的兼容性问题

常见问题

Q: AutoMigrate 会删除数据吗?

A: 不会,AutoMigrate 只会添加或修改表结构,不会删除数据。

Q: 如何处理列重命名?

A: AutoMigrate 不支持列重命名,需要使用 Migrator API 手动处理。

Q: 如何回滚迁移?

A: 需要自己实现回滚逻辑,GORM 不提供自动回滚功能。

Q: 如何处理大型表的迁移?

A: 考虑使用在线 DDL 工具或分批处理数据。

标签:Gorm