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

How to use GORM's AutoMigrate feature?

3月6日 21:37

GORM's AutoMigrate feature can automatically create and update database table structures, keeping the database schema synchronized with Go structs.

Basic Usage of AutoMigrate

Basic Migration

go
// Auto migrate User model db.AutoMigrate(&User{}) // Migrate multiple models db.AutoMigrate(&User{}, &Profile{}, &Order{}) // Migrate all models db.AutoMigrate( &User{}, &Profile{}, &Order{}, &Product{}, )

Model Definition and Tags

Basic Model

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"` }

Using gorm.Model

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

Common Tags

Primary Key

go
ID uint `gorm:"primaryKey"`

Field Type

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

Field Size

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

Default Value

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

Not Null Constraint

go
Name string `gorm:"not null"`

Unique Index

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

Regular Index

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

Composite Index

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

Custom Table Name

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

Ignore Field

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

Advanced Migration Features

Add Foreign Key

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

Many-to-Many Relationship

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;"` }

Embedded Struct

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

Migration Limitations

What AutoMigrate Won't Do

  • Won't drop columns
  • Won't rename columns
  • Won't drop tables
  • Won't modify column types (may cause data loss)

Manual Handling of Complex Changes

go
// Add column db.Migrator().AddColumn(&User{}, "NewField") // Drop column db.Migrator().DropColumn(&User{}, "OldField") // Rename column db.Migrator().RenameColumn(&User{}, "OldName", "NewName") // Add index db.Migrator().CreateIndex(&User{}, "Email") // Drop index db.Migrator().DropIndex(&User{}, "Email") // Rename index db.Migrator().RenameIndex(&User{}, "OldIndex", "NewIndex") // Check if table exists hasTable := db.Migrator().HasTable(&User{}) // Drop table db.Migrator().DropTable(&User{}) // Rename table db.Migrator().RenameTable("old_users", "new_users")

Migration Best Practices

1. Version Control

go
type Migration struct { ID uint `gorm:"primaryKey"` Name string `gorm:"unique"` AppliedAt time.Time `gorm:"autoCreateTime"` } func RunMigrations(db *gorm.DB) error { // Migrate table structure if err := db.AutoMigrate(&User{}, &Profile{}); err != nil { return err } // Migrate data 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. Data Migration

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. Rollback Mechanism

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") }, }, }

Notes

  1. Production Caution: Use AutoMigrate very carefully in production, verify in test environment first
  2. Data Backup: Always backup data before executing migrations
  3. Version Control: Include migration scripts in version control
  4. Test Coverage: Write comprehensive tests for migration logic
  5. Performance Considerations: Migrations of large tables may take a long time, consider batch processing
  6. Compatibility: Pay attention to compatibility issues across different databases

Common Questions

Q: Will AutoMigrate delete data?

A: No, AutoMigrate only adds or modifies table structures, it does not delete data.

Q: How to handle column renaming?

A: AutoMigrate does not support column renaming, you need to use Migrator API to handle it manually.

Q: How to rollback migrations?

A: You need to implement rollback logic yourself, GORM does not provide automatic rollback functionality.

Q: How to handle migrations for large tables?

A: Consider using online DDL tools or processing data in batches.

标签:Gorm