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
gotype 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
gotype User struct { gorm.Model Name string `gorm:"size:100;not null"` Email string `gorm:"size:100;uniqueIndex"` }
Common Tags
Primary Key
goID uint `gorm:"primaryKey"`
Field Type
goName string `gorm:"type:varchar(100)"` Age int `gorm:"type:tinyint"` Price float64 `gorm:"type:decimal(10,2)"`
Field Size
goName string `gorm:"size:100"`
Default Value
goAge int `gorm:"default:0"` Status string `gorm:"default:'active'"`
Not Null Constraint
goName string `gorm:"not null"`
Unique Index
goEmail string `gorm:"unique"` Email string `gorm:"uniqueIndex"`
Regular Index
goName string `gorm:"index"` Name string `gorm:"index:idx_name"`
Composite Index
gotype User struct { Name string `gorm:"index:idx_name_age"` Age int `gorm:"index:idx_name_age"` }
Custom Table Name
gotype User struct { gorm.Model Name string } func (User) TableName() string { return "sys_users" }
Ignore Field
gotype User struct { Name string Password string `gorm:"-"` TempField string `gorm:"-"` }
Advanced Migration Features
Add Foreign Key
gotype Profile struct { gorm.Model UserID uint `gorm:"not null;index"` User User `gorm:"foreignKey:UserID;references:ID"` Bio string }
Many-to-Many Relationship
gotype 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
gotype 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
gotype 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
gofunc 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
gotype 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
- Production Caution: Use AutoMigrate very carefully in production, verify in test environment first
- Data Backup: Always backup data before executing migrations
- Version Control: Include migration scripts in version control
- Test Coverage: Write comprehensive tests for migration logic
- Performance Considerations: Migrations of large tables may take a long time, consider batch processing
- 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.