目录
- nav:
title: 指令
order: 3
title: migrate
order: 10
toc: content - 视频教程
- 应用场景:
- 目录说明
- 数据迁移
- 迁移步骤
- 配置数据库
- 常用命令示例
- 新建模型实例
- 更新模型实例
nav:
title: 指令
order: 3
title: migrate
order: 10
toc: content
视频教程
【go-admin-pro】如何优雅的数据迁移?migrate 指令
【go-admin-pro】数据迁移 migrate 指令常见的问题说明
应用场景:
- 迁移新表
- 变更表字段,表字段的新增、删除、修改
- 预置表数据
目录说明
注意:
迁移关联数据时,如何有外键约定,需要先执行写入表数据,再执行写入关系数据,不然会报错,参考 port_groups_relation.sql
表
├── migration
│ ├── init.go # 迁移类
│ ├── models #迁移模型 (go-admin系统已开发过的功能)
│ ├── version-local # 新开发迁移文件 大家在这里开发
│ └── version #go-admin系统系统迁移文件 (已开发过的功能 不要动这里的文件,以免影响后面升级)
│ ├── 1599190683659_tables_tables.go # 迁移表
│ ├── 1653638869132_migrate.go # 迁移预置数据
│ └── doc.go # 预置数据
└── server.go # cobra.Command 命令行文件
数据迁移
在开发过程中经常会遇到数据库字段的变更和基础数据的变更,go-admin
提供了对应的迁移工具;
首先需要将在项目根目录下执行go build
将程序编译:
go build
执行go-admin migrate
指令,可以进行数据迁移;
首次使用时可以使用-h
查看帮助信息;
$ ./go-admin migrate -h
Initialize the database
Usage:
go-admin migrate [flags]
Examples:
go-admin migrate -c config/settings.yml
Flags:
-c, --config string Start server with provided configuration file (default "config/settings.yml")
-d, --domain string select tenant host (default "*")
-g, --generate generate migration file
-a, --goAdmin generate go-admin migration file
-h, --help help for migrate
迁移步骤
- 配置数据库配置
- 生成迁移文件
- 修改迁移文件
- 创建迁移模型
- 执行迁移命令
配置数据库
修改配置文件里数据库链接信息(database
)
config/settings.dev.yml
常用命令示例
go run main.go migrate -h # 帮助
go run main.go migrate -g true -a true -c config/settings.dev.yml # 生成 go-admin系统预置 迁移文件
go run main.go migrate -g true -c config/settings.dev.yml # 生成 自定义功能 迁移文件 自己开发新功能用这个功能
go run main.go migrate -c config/settings.dev.yml # 执行迁移命令 迁移 未迁移过的 文件
参数说明:
-h # 帮助
-c # 指定配置文件 默认使用 -c config/settings.yml 配置文件
-a # 生成 系统预置 迁移文 生成到` cmd/migrate/migration/version ` go-admin系统迁移文件在这目录里操作,最好不要动,方便同步升级
-g # 生成迁移文 生成到` cmd/migrate/migration/version-local ` 自己开发新功能的迁移文件在这目录里操作
新建模型实例
- 生成迁移文件
首先执行,
$ ./go-admin migrate -a true -g true
generate migration file
完成后,我们打开cmd/migrate/migration/version
目录,这时里边已经为您新添加了一个迁移文件1654233005297_migrate.go
(一般会在最下边):
提示:
迁移文件名版本号不要修改,后面的名称可以随便修改为有语意的名称,方便后续维护迁移文件。
例 1654233005297_migrate.go
修改为 1654233005297_CreateTable_TbDemoTest.go
,见名知意,创建tb_demo_test
表
打开文件,我们打开看一下
package version
import (
"gorm.io/gorm"
"runtime"
"go-admin/cmd/migrate/migration"
common "go-admin/common/models"
)
func init() {
_, fileName, _, _ := runtime.Caller(0)
migration.Migrate.SetVersion(migration.GetFilename(fileName), _1654233005297Test)
}
func _1654233005297Test(db *gorm.DB, version string) error {
return db.Transaction(func(tx *gorm.DB) error {
// TODO: 这里开始写入要变更的内容
// TODO: 例如 修改表字段 使用过程中请删除此段代码
//err := tx.Migrator().RenameColumn(&models.SysConfig{}, "config_id", "id")
//if err != nil {
// return err
//}
// TODO: 例如 新增表结构 使用过程中请删除此段代码
//err = tx.Migrator().AutoMigrate(
// new(models.CasbinRule),
// )
//if err != nil {
// return err
//}
return tx.Create(&common.Migration{
Version: version,
}).Error
})
}
- 接下来只要按照文件里边的代码提示编写即可。
package version
import (
"go-admin/cmd/migrate/migration/models"
"gorm.io/gorm"
"runtime"
"go-admin/cmd/migrate/migration"
common "go-admin/common/models"
)
func init() {
_, fileName, _, _ := runtime.Caller(0)
migration.Migrate.SetVersion(migration.GetFilename(fileName), _1654233005297Test)
}
func _1654233005297Test(db *gorm.DB, version string) error {
return db.Transaction(func(tx *gorm.DB) error {
// TODO: 这里开始写入要迁移的表构型
err := tx.Debug().Migrator().AutoMigrate(
new(models.TbDemoTest1654233005297),
)
if err != nil {
//如果错误就报错,停止迁移
return err
}
return tx.Create(&common.Migration{
Version: version,
}).Error
})
}
// TbDemoTest表模型 建议带上版本号和生成文件名前缀一致
type TbDemoTest1654233005297 struct {
models.Model
Name string `json:"name" gorm:"type:varchar(128);comment:名称"`
models.ModelTime
models.ControlBy
}
func (TbDemoTest1654233005297) TableName() string {
return "tb_demo_test" # 指定表名
}
上边我们给出了一个简单的struct
,包含的有Model
、ModelTime
、ControlBy
和Name
属性;
其中Model
、ModelTime
、ControlBy
是 go-admin
默认需要添加的基本属性,Name
是业务属性;
另外还需要定义一个TableName()
的func
用来设置我们的表名称;
- 执行迁移。
:::warning
温馨提醒,请认真阅读
数据库操作建议做好检查确认脚本,另外确认完成 cmd/migrate/migration/version
目录中只有新建的文件没有被执行过(已迁移过的文件,不会再次迁移),
因为执行迁移指令的过程中,系统会检查没有执行过的迁移脚本(sys_migration 表中 version 字段里值和 cmd/migrate/migration/version
目录中的文件对比),
将未执行的脚本全部执行;迁移前做好数据备份
当然,相反如果迁移过的文件,想要再次迁移,也可删除sys_migration表中对应版本信息的那条记录,即可以再次执行迁移文件(调适时可以试试,呵呵)。
:::
3.1 方式一:不编译运行(推荐)
注意:
不带 -c config/settings.dev.yml
默认使用 -c config/settings.yml
配置文件
# 执行迁移
$ go run main.go migrate -c config/settings.dev.yml
3.2 方式二:编译并运行迁移
# 不推荐,每次修改迁移文件后,都需要 go build 重新编译,容易忘记编译,掉进坑里,嘿嘿。。。
$ go build
$ ./go-admin migrate -c config/settings.dev.yml # mac /linux执行命令
$ ./go-admin.exe migrate -c config/settings.dev.yml # windows执行命令
# 注意:sqlite 需要加 -tags=sqlite3.json1参数
$ go run -tags=sqlite3,json1 main.go migrate
3.3 方式三:golangIDE
运行
golangIDE
还要以进行debug 断点调适迁移文件,(推荐)
migrate -c config/settings.dev.93.yml -g true -g true
执行成功后检查数据库的对应信息,和预期一样就迁移成功,会生成tb_demo_test
表。
更新模型实例
我们以修改字段名称为例:
- 生成迁移文件
首先执行,
$ ./go-admin migrate -a true -g true
generate migration file
完成后,我们打开cmd/migrate/migration/version
目录,这时里边已经为您新添加了一个迁移文件1660151543503_migrate
(一般会在最下边),我们打开看一下:
package version
import (
"gorm.io/gorm"
"runtime"
"go-admin/cmd/migrate/migration"
common "go-admin/common/models"
)
func init() {
_, fileName, _, _ := runtime.Caller(0)
migration.Migrate.SetVersion(migration.GetFilename(fileName), _1660151543503Test)
}
func _1660151543503Test(db *gorm.DB, version string) error {
return db.Transaction(func(tx *gorm.DB) error {
// TODO: 这里开始写入要变更的内容
// TODO: 例如 修改表字段 使用过程中请删除此段代码
//err := tx.Migrator().RenameColumn(&models.SysConfig{}, "config_id", "id")
//if err != nil {
// return err
//}
// TODO: 例如 新增表结构 使用过程中请删除此段代码
//err = tx.Migrator().AutoMigrate(
// new(models.CasbinRule),
// )
//if err != nil {
// return err
//}
return tx.Create(&common.Migration{
Version: version,
}).Error
})
}
-
修改迁移脚本
接下来只要要按照文件里边的提示修改代码即可。package version import ( "gorm.io/gorm" "runtime" "go-admin/cmd/migrate/migration" common "go-admin/common/models" ) func init() { _, fileName, _, _ := runtime.Caller(0) migration.Migrate.SetVersion(migration.GetFilename(fileName), _1660151543503Test) } func _1660151543503Test(db *gorm.DB, version string) error { return db.Transaction(func(tx *gorm.DB) error { // TODO: 例如 修改表字段 第二个参数标明需要修改的字段名 err := tx.Migrator().AddColumn(&TbDemoTest1660151543503{}, "Desc") if err != nil { return err } return tx.Create(&common.Migration{ Version: version, }).Error }) } // TbDemoTest表模型 这里建议带上版本号和生成文件名前缀一致 type TbDemoTest1660151543503 struct { models.Model Name string `json:"name" gorm:"type:varchar(128);comment:名称"` Desc string `json:"desc" gorm:"type:varchar(255);comment:描述"` //需要添加的字段 models.ModelTime models.ControlBy } func (TbDemoTest1660151543503) TableName() string { return "tb_demo_test" # 指定表名 }
-
执行迁移
:::warning
温馨提醒,请认真阅读
数据库操作建议做好检查确认脚本,另外确认完成 cmd/migrate/migration/version
目录中只有新建的文件没有被执行过(已迁移过的文件,不会再次迁移),因为执行迁移指令的过程中,系统会检查没有执行过的迁移脚本(sys_migration 表中 version 字段里值和 cmd/migrate/migration/version
目录中的文件对比),将未执行的脚本全部执行;迁移前做好数据备份
:::
-
执行迁移
# 方式一:不编译运行(推荐) $ go run main.go migrate # 方式二:编译并运行迁移 注意:不带 -c config/settings.dev.yml 默认使用 -c config/settings.yml 配置文件 $ go build $ ./go-admin migrate -c config/settings.dev.yml # mac /linux执行命令 $ ./go-admin.exe migrate -c config/settings.dev.yml # windows执行命令 注意:sqlite 需要加 -tags=sqlite3.json1参数 $ go run -tags=sqlite3,json1 main.go migrate
执行成功后检查数据库的对应信息,和预期一样就迁移成功了,tb_demo_test
会添加上desc
字段。