5月29日 01:21
How to use GORM's AutoMigrate feature?
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.