目录

文章目录

  • 目录
  • 前言
  • gormigrate
  • 核心结构体
  • 实现分析
    • 版本定义
      • InitSchema
      • Migration
    • 版本记录(历史)
    • 版本升级和回退

前言

  • GORM v2
  • gormigrate v2
  • 程序 Demo:https://github.com/JmilkFan/gormigrate-demo

gormigrate

GORM 本身提供了 AutoMigrate 功能以及 Migrator 提供的 DDL 接口,但 GORM 更加专注于 ORM 层面,所以在 ORM Schema Version Control(数据库版本控制)有所欠缺。而 gormigrate 就是一个轻量化的 Schema Migration Helper(迁移助手),基于 GORM AutoMigrate 和 Migrator 进行封装,用于弥补这一块的缺失。

  • Github:https://github.com/go-gormigrate/gormigrate

需要注意的是,简洁清理是 gormigrate 最大的优势也是不足,如果是大型系统有着复杂的版本控制要求,则建议使用 golang-migrate/migrate。

核心结构体

gormigrate 的核心 Struct 是 Gormigrate:

// Gormigrate represents a collection of all migrations of a database schema.
type Gormigrate struct {db         *gorm.DB         // DBClient 实例tx         *gorm.DB           // 事务型 DBClient 实例options    *Options           // migrations 配置选项migrations []*Migration       // 版本迁移 SchemasinitSchema InitSchemaFunc    // 版本初始化 Schemas
}
  • DBClient 实例:最基础的,也是最通用的 GORM DBClient 实例。

  • 事务型 DBClient 实例:也是 GORM 的 DBClient 实例,区别在于会使用 RDBMS 的 Transaction(事务)特性来执行 GORM 封装好的 Migrator DDL。注意,是都支持事务性 DBClient 跟 RDBMS 的类型有关。

  • migrations 配置选项:用于配置 migrate 的执行细节。

type Options struct {TableName string        // 指定 migrations 版本记录表的表名,默认为 migrations。IDColumnName string     // 指定 migrations 版本记录表的列名,默认为 id。IDColumnSize int        // 指定 migrations 版本记录表的列属性,默认为 varchar(255)。UseTransaction bool      // 指定是否使用 Transaction 来执行 GORM Migrator DDL。ValidateUnknownMigrations bool  // 指定当 migrations 版本记录表有非法记录时,是否触发 ErrUnknownPastMigration 错误。
}
  • 版本迁移 Schemas:用于定义版本迁移的 Schemas。
  • 版本初始化 Schemas:用于定义版本初始化的 Schemas。

实现分析

ORM Schema Version Control 需要具备的最基本功能元素:

  • 版本定义
  • 版本记录(历史)
  • 版本升级
  • 版本回退

版本定义

正如上文介绍到的,gormigrate 大体上支持两种类型的版本定义:

  • 版本迁移 Schemas:用于定义版本迁移的 Schemas。
  • 版本初始化 Schemas:用于定义版本初始化的 Schemas。

InitSchema

应用于 init_database_no_table 的场景,可以通过调用 Gormigrate 的 InitSchema 方法注册一个版本初始化 Schemas 函数 “InitSchemaFunc”,并在一个新的干净的数据库中运行它,完成一次全量建表的过程。注意,InitSchema 是没有 Rollback 的。

函数签名:

// InitSchemaFunc is the func signature for initializing the schema.
type InitSchemaFunc func(*gorm.DB) error

示例:

type Person struct {gorm.ModelName stringAge int
}type Pet struct {gorm.ModelName     stringPersonID int
}m := gormigrate.New(db, gormigrate.DefaultOptions, []*gormigrate.Migration{// you migrations here
})m.InitSchema(func(tx *gorm.DB) error {err := tx.AutoMigrate(&Person{},&Pet{},// all other tables of you app)if err != nil {return err}if err := tx.Exec("ALTER TABLE pets ADD CONSTRAINT fk_pets_people FOREIGN KEY (person_id) REFERENCES people (id)").Error; err != nil {return err}// all other foreign keys...return nil
})

Migration

应用于完成初始化之后的 “增量迁移” 场景,可以通过调用 Gormigrate 的 Migration 方法注册一个 MigrateFunc 和一个 RollbackFunc 函数,前者用于 Upgrade,后者则是对应的 Downgrade,以此来完成 Schema 的升级和回退。

NOTE:当我们使用 InitSchema 和 Migration 方法的时候切记不能使用同一个 Gormigrate 实例,否则会出现只执行 InitSchema 不执行 Migration 的情况,导致数据库版本无法迁移到 Latest 的现象。因为 InitSchema 在 DDL 建表的时候会把 Migration 的版本记录都插入到 migrations 表里面去,但实际上并没有执行 Migration 的 DDL。

函数签名:

// MigrateFunc is the func signature for migrating.
type MigrateFunc func(*gorm.DB) error// RollbackFunc is the func signature for rollbacking.
type RollbackFunc func(*gorm.DB) error

示例:

package mainimport ("log""github.com/go-gormigrate/gormigrate/v2""gorm.io/gorm"_ "github.com/jinzhu/gorm/dialects/sqlite"
)func main() {db, err := gorm.Open("sqlite3", "mydb.sqlite3")if err != nil {log.Fatal(err)}db.LogMode(true)m := gormigrate.New(db, gormigrate.DefaultOptions, []*gormigrate.Migration{// create persons table{ID: "201608301400",Migrate: func(tx *gorm.DB) error {// it's a good pratice to copy the struct inside the function,// so side effects are prevented if the original struct changes during the timetype Person struct {gorm.ModelName string}return tx.AutoMigrate(&Person{})},Rollback: func(tx *gorm.DB) error {return tx.Migrator().DropTable("people")},},// add age column to persons{ID: "201608301415",Migrate: func(tx *gorm.DB) error {// when table already exists, it just adds fields as columnstype Person struct {Age int}return tx.AutoMigrate(&Person{})},Rollback: func(tx *gorm.DB) error {return tx.Migrator().DropColumn("people", "age")},},// add pets table{ID: "201608301430",Migrate: func(tx *gorm.DB) error {type Pet struct {gorm.ModelName     stringPersonID int}return tx.AutoMigrate(&Pet{})},Rollback: func(tx *gorm.DB) error {return tx.Migrator().DropTable("pets")},},})if err = m.Migrate(); err != nil {log.Fatalf("Could not migrate: %v", err)}log.Printf("Migration did run successfully")
}

版本记录(历史)

同样的,gormigrate 也为 InitSchema 和 Migration 提供了两种版本记录的方式,前者的 Version ID 硬编码为 SCHEMA_INIT,后者的 Version ID 则为自定义的 Migration struct 的 ID 字段:

// Migration represents a database migration (a modification to be made on the database).
type Migration struct {// ID is the migration identifier. Usually a timestamp like "201601021504".ID string// Migrate is a function that will br executed while running this migration.Migrate MigrateFunc// Rollback will be executed on rollback. Can be nil.Rollback RollbackFunc
}

而 Version History 则是数据库表 migrations 中的记录:

test_db=# select * from migrations;id
-------------SCHEMA_INITv1v2v3
(4 行记录)

gormigrate 通过 Version History 记录来控制版本的升级和回退,如果已经升级完成(存在记录)的版本则不会被重复执行,否者就会进行全量的初始化或增量的升级。

版本升级和回退

从 Migration 的示例中可以看出,gormigrate 本质上是在封装 GORM 的 AutoMigrate 和 Migrator DDL 接口的基础之上实现了版本记录的功能,所以执行版本升级和回退的实现依旧来自于 GORM 的能力。

对此,笔者在《Go 语言编程 — gorm 数据库版本迁移》已经有过介绍,这里就不再赘述了。

此外,Gormigrate 还提供了

  • MigrateTo:升级到指定 ID 的版本。
  • RollbackTo:回退到指定 ID 的版本。
  • RollbackLast:撤消上一次迁移。
  • RollbackMigration:执行自定义的回退函数。

通过这些方法,已经可以在一定程度上满足数据库应用程序在 ORM Schames Version Control 上的需求了。

Go 语言编程 — gormigrate GORM 的数据库迁移助手相关推荐

  1. 不同库表数据库迁移工具_Microsoft提供的数据库迁移助手工具概述

    不同库表数据库迁移工具 This article gives the overview of the Database Migration Assistant Tool to access, plan ...

  2. Go 语言编程 — gorm 数据库版本迁移

    目录 文章目录 目录 前言 AutoMigrate 示例 Migrator 接口(DDL 操作方法) 表操作 列操作 约束操作 索引操作 数据库版本控制 参考文档 前言 本文示例为 GORM V2.0 ...

  3. Go 语言编程 — gorm ORM 框架

    目录 文章目录 目录 实现一个关系型数据库应用程序需要做什么? GORM 连接数据库 表定义 Module Struct tags 表操作 db.HasTable 表是否存在 db.CreateTab ...

  4. 数据库笔记09:Transact-SQL语言编程基础

    /*********************************  第九单元 Transact-SQL语言编程基础 ***********************************/ /* ...

  5. Linux下安装MySQL数据库以及用C语言编程存取数据库

    ubuntu下安装软件相当简单,一条简单的 apt-get install 就可以解决,相比源码安装方式唯一的缺点就是,你无法自定义软件的安装目录.不过这也不是什么太大的缺点.下面我们就用 apt-g ...

  6. 聊天室(C语言)- 基于文件编程、网络通信、数据库实现

    聊天室(C语言) 源码连接 https://download.csdn.net/download/G1842965496/83970608 项目面试问题 C/C++/嵌入式-面试题汇总 --基于文件编 ...

  7. linux下C语言编程操作数据库(sqlite3)

    前言:C语言中通过调用 sqlite 的函数接口来实现对数据库的管理(创建数据库.创建表格.插入数据.查询.数据.删除数据等),掌握sqlite数据库的语法,以及sqlite提供的函数接口,那么在li ...

  8. Go语言编程笔记16:存储数据

    Go语言编程笔记16:存储数据 图源:wallpapercave.com 几乎任何程序都绕不开读写数据,只不过具体的数据存储介质和方式有所不同.本篇文章将从多种数据存储方式进行探讨各种存储方式如何实现 ...

  9. C/C++语言编程的隐患!

    C/C++语言编程的隐患! 本文将带您了解一些良好的和内存相关的编码实践,以将内存错误保持在控制范围内.内存错误是 C 和 C++ 编程的祸根:它们很普遍,认识其严重性已有二十多年,但始终没有彻底解决 ...

最新文章

  1. 产生螺旋分类样本集合 SpiralData
  2. 1024X768大图 (Wallpaper)
  3. multipath管理存储多路径
  4. 最长公共子字符串(动态规划)
  5. 存钱吃利息存邮政储蓄好还是农业银行好?
  6. 微软发布Azure Pipelines,开源项目可无限制使用CI/CD
  7. 【I】ZF2安装 和 创建一个新项目
  8. Hive、Spark优化案例
  9. 常用软件版本号及软件安装包格式
  10. SQL 2008客户端ODBC配置DSN时使用网络登录ID的windows NT验证登录时 报18452错误
  11. 游戏运营的工作中是做什么
  12. ae合成设置快捷键_AE设计首选快捷键大全+解析
  13. 【通信仿真】Aloha协议仿真含Matlab源码
  14. vue利用 canvas 在图片上加文字
  15. python 曲线平滑_曲线平滑(smoothing)
  16. 春考计算机专业PS考点,春考辅导:春考PS的学习方法和技巧
  17. 尘埃落定性描写细节摘要_解释“细节”和“摘要”元素
  18. 利用VMware搭建centos环境
  19. CS硕士妹子找工作杂谈(转载,北邮)
  20. 3D飞机动画网页js特效代码

热门文章

  1. python调用dll时路径问题_IDEA 使用 JNA 时,DLL 文件路径问题
  2. vue openlayer单击地图事件循环多次执行_VUE生命周期函数面试题
  3. android x86 三星,三星主刀 X86架构Android4.X手机CES见
  4. java gui 选项_【Java-GUI】04 菜单
  5. seaborn系列 (4) | 分类图catplot()
  6. JAVA实现旋转数组的最小数字问题(《剑指offer》)
  7. centos apache php mysql zend_CentOS 5.5搭建Apache+PHP5.2x+MySQL5+Zend3(yum安装)
  8. arcgis andin使用python窗体_在ArcGIS?10中使用python
  9. 中国医疗AI第一股首位投资人:AI不再高深,正在回归商业本质
  10. 武装机器狗不会自主杀人,监管自主杀伤性武器是政府的事,机器狗公司CEO这样说...