初识GORM

什么是ORM

Object-Relationl Mapping, 它的作用是映射数据库和对象之间的关系,方便我们在实现数据库操作的时候不用去写复杂的sql语句,把对数据库的操作上升到对于对象的操作。

什么是GORM

顾名思义,gorm = go + orm,即基于go语言实现的orm库
v1版本github地址:https://github.com/jinzhu/gorm
v2版本github地址:https://github.com/go-gorm/gorm
官网地址:https://gorm.io/zh_CN/
官方文档地址:https://gorm.io/zh_CN/docs/index.html

GORM 结构标记

安装过程以及简单的curd,大家看下官方文档即可,使用起来还是比较方便的,也与其他的orm没有大的区别,这里想先提下gorm中的结构标记

大家都知道,orm是完成了数据表和对象之间的映射,而这个对象的结构、字段等等,都是需要我们在程序中定义出来的,但是gorm中有一点与以往不同,gorm中提供了功能强大丰富的结构标记

type User struct {
    ID         int64
    Number     int64
    Name       string
    ImgURL    string
    CreatedAt  time.Time
    UpdatedAt  time.Time
}

再辅以AutoMigrate方法,就可以让我们直接通过代码生成对应的数据表,这一逆向操作起初应该是不甚习惯的,毕竟大多数情况下来说,我们的习惯还是先设计出数据表,然后给映射出对象,再给这个对象添加功能、使用对象完成逻辑实现等

但其实我们自己也经常会遇到这样的情况,设计出数据表后,往往在实际开发业务时候,或者在之后的迭代中,会发现我们的数据表需要一点点的打补丁,添加或者修改字段等等,其实道理也很明白,一时的设计,很难满足未出现的需求,而需求是不断更新迭代的,设计自然需要迎合和适应。

基于这个观点,我认为这个逆向的过程确实是一个值得思考的点,当然这里也会有很多问题:比如增加信息同步成本、增加高效协作难度等等

好,回归正题,我们先来看下部分常用的标签们:

type User struct {
    ID         int64        `gorm:"type:bigint(20);primary_key;autoIncrement"`
    Number     int64        `gorm:"<-:create;index:idx_number"`
    Name       string       
    ImgURL     string       `gorm:"column:name"`
    CreatedAt  time.Time    `gorm:"autoCreateTime"`
    UpdatedAt  time.Time    `gorm:"autoUpdateTime"`
}
  • primary_key 指定主键,可以不指定在id字段上
  • type 指定字段类型
  • autoIncrement 自增
  • <-:false,跟 chan 相似左箭头为写,右箭头为读, create代表只能创建时写
  • index 创建索引,冒号后跟索引名称,可为空,相同非空名称的索引会创建联合索引
  • autoCreateTime 自动s为单位填充创建时间
  • autoUpdateTime 自动s为单位填充更新时间
  • column 这个类似json标签,用于字段映射时,无法直接通过首字母大小写的转化和驼峰和下划线互转等操作,完成字段和数据库列名直接映射上的情况,直接指定列名

对于其他标签,以及一些比较高级的索引约束复合主键标签,大家可以参看官方文档

GORM v2 更新内容摘要

Context 支持

增加原生支持ctx

create 支持批量创建

  • 生成一条语句来进行插入(难不成还遍历?)
  • 数据有关联的将会调用upsert
  • 批量插入依然会调用钩子方法

upsert

clause.OnConflict 将会提供upsert支持

import "gorm.io/gorm/clause"

DB.Clauses(clause.OnConflict{DoNothing: true}).Create(&users)

支持嵌套事务

SavePoint,RollbackTo

事务操作将会更加丰富

字段权限 和 更新、创建时间追踪

还记得上面标签提高的<-:creategorm:"autoCreateTime等吗,对的,v2.0开始支持

Prometheus

增加Prometheus插件支持来收集 DBStats 和用户自定义指标
Prometheus插件简介

tableName 不再允许动态表名

func (User) TableName() string {
  return "t_user"
}

当然,以后使用动态表名可以使用scope实现

func UserTable(u *User) func(*gorm.DB) *gorm.DB {
  return func(db *gorm.DB) *gorm.DB {
    return db.Table("user_" + u.Role)
  }
}

DB.Scopes(UserTable(&user)).Create(&user)

Migrator(迁移)将会更加强大

gorm 迁移

总结

总的来说,gorm是一个很遍历,足够强大,值得深挖源码,深入学习的orm,燥起来!

引用

gorm 声明模型
gorm 索引标签
gorm 约束标签
gorm 复合主键标签
gorm 迁移


欢迎大家关注我的公众号,一起交流