前言
GORM个人总结由本人跟学教材时的个人理解与做题总结而来,难免具有很多错误,如发现请指正,谢谢!
电脑端可以于左栏“文章目录”来索引到指定小节,手机端可以通过左上角按钮唤出菜单索引到指定小节
简介
ORM
ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象与关系数据库相互映射
理解:ORM让数据库里面的表结构变为代码定义的数据结构,从而做到代码结构即为数据库结构,代码行为即数据库行为
正文
连接到数据库
DSN
标准格式:
student:luckyqu717@tcp(127.0.0.1:3306)/GORM_Learn?charset=utf8mb4&parseTime=True&loc=Local
其中的parseTime如果在此没有设置为true,在使用查询的时候会报错,因为没有将db内的时间转换为go中的time.time类型
操作
在使用GORM连接数据库只需要像sql包中的Open函数类似,传入一个DSN去让GORM和数据库建立连接,就像这样:
db, err := gorm.Open("mysql", dsn)
但一般使用下面这种方式,可以去设置一些参数以设置
db, err := gorm.Open(mysql.New(mysql.Config{}),&gorm.Config{})
其中,gorm的配置文件中有几项较为常用的设置如下所示:
//跳过默认事务,gorm中进行crud操作是以事务的形式进行,默认为不跳过,开启后处理速度会得到提升,但是数据处理安全可能会下降,建议不跳过
SkipDefaultTransaction
//新建表的命名规则
Namingstrategy
//其中,schema包中的NamingStrategy服务于这个参数,可以设置一些基础的命名规则,如:
//增加前缀
TablePrefix
//启用单数表名
SingulerTable
//示例:
NamingStrategy:schema.NamingStrategy{
TablePrefix:"t_"
SingulerTable:true
}
//建表时是否跳过外键约束,建议是跳过,从而大幅提高数据库运行速度,设置为true,建表的时候将不会建立物理外键,现在主张为逻辑外键,在代码里自动提现逻辑关系建议设置为true
DisableForeignKeyConstrainWhenMigrating
表的相关操作
使用DropTable来删除一个表
使用CreateTable来创建一个表
使用Rename来改名一个表
模型
概念
gorm的模型为一个实现了gorm的接口或者携带了gorm的标签的结构体
约定
一些约定(可以用文档中的方法进行改动):
- 主键:GORM 使用一个名为
ID
的字段作为每个模型的默认主键。 - 表名:默认情况下,GORM 将结构体名称转换为
snake_case
并为表名加上复数形式。 例如,一个User
结构体在数据库中的表名变为users
。 - 列名:GORM 自动将结构体字段名称转换为
snake_case
作为数据库中的列名。 - 时间戳字段:GORM使用字段
CreatedAt
和UpdatedAt
来自动跟踪记录的创建和更新时间。
gorm中提供了符合约定的结构体(gorm.Model),可以将它嵌入进自定义的结构体中以遵守约定
// gorm.Model 的定义
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
ID
:每个记录的唯一标识符(主键)。CreatedAt
:在创建记录时自动设置为当前时间。UpdatedAt
:每当记录更新时,自动更新为当前时间。DeletedAt
:用于软删除(将记录标记为已删除,而实际上并未从数据库中删除)。
标签
可以使用gorm的标签来进行包括但不限于注释,列唯一,索引,列名的操作改动,在定义的结构体字段后使用反括号来对一个字段打上标签
以下是标签名称及其用处:
column | 指定 db 列名 |
type | 列数据类型,推荐使用兼容性好的通用类型,例如:所有数据库都支持 bool、int、uint、float、string、time、bytes 并且可以和其他标签一起使用,例如:not null 、size , autoIncrement … 像 varbinary(8) 这样指定数据库数据类型也是支持的。在使用指定数据库数据类型时,它需要是完整的数据库数据类型,如:MEDIUMINT UNSIGNED not NULL AUTO_INCREMENT |
serializer | 指定将数据序列化或反序列化到数据库中的序列化器, 例如: serializer:json/gob/unixtime |
size | 定义列数据类型的大小或长度,例如 size: 256 |
primaryKey | 将列定义为主键 |
unique | 将列定义为唯一键 |
default | 定义列的默认值 |
precision | 指定列的精度 |
scale | 指定列大小 |
not null | 指定列为 NOT NULL |
autoIncrement | 指定列为自动增长 |
autoIncrementIncrement | 自动步长,控制连续记录之间的间隔 |
embedded | 嵌套字段 |
embeddedPrefix | 嵌入字段的列名前缀 |
autoCreateTime | 创建时追踪当前时间,对于 int 字段,它会追踪时间戳秒数,您可以使用 nano /milli 来追踪纳秒、毫秒时间戳,例如:autoCreateTime:nano |
autoUpdateTime | 创建/更新时追踪当前时间,对于 int 字段,它会追踪时间戳秒数,您可以使用 nano /milli 来追踪纳秒、毫秒时间戳,例如:autoUpdateTime:milli |
index | 根据参数创建索引,多个字段使用相同的名称则创建复合索引,查看 索引 获取详情 |
uniqueIndex | 与 index 相同,但创建的是唯一索引 |
check | 创建检查约束,例如 check:age > 13 ,查看 约束 获取详情 |
<- | 设置字段写入的权限, <-:create 只创建、<-:update 只更新、<-:false 无写入权限、<- 创建和更新权限 |
-> | 设置字段读的权限,->:false 无读权限 |
– | 忽略该字段,- 表示无读写,-:migration 表示无迁移权限,-:all 表示无读写迁移权限 |
comment | 迁移时为字段添加注释 |
增删改查
可以使用Row方法来使用原生sql语句进行操作
以下的删,改,查操作都可以使用检索方法进行精确操作(详见官方文档)
以下CRUD操作调用的都为*gorm.DB的方法,以下不再赘述
检索
主键检索,在first方法的第二个参数传入主键参数进行查询
String检索,调用Where方法传入表达式进行查询(占位符为?)
结构体&Map检索,调用Where方法传入一个结构体或者Map进行检索
增
使用Create方法,接收一个结构体或者结构体切片从而将内部数据写入数据库,返回一个消息结构体,内包含错误等消息,可以用errors.Is()方法来对两种错误进行比对
删
使用Delete方法,对表中的数据进行软删除(仍在表中),在前面使用Unscoped修饰进行硬删除(不在表中)
改
使用Update方法,更新所选字段
使用Updates方法,更新传入的结构体的所有字段,零值不进行更新,可以传入map从而更新零值
使用Save方法,对全部字段都进行更新,包括零值在内
查
使用以下方法对数据进行查找:
//查询主键排序后的第一条
First()
//查询第一条(不排序)
Take()
//查询主键排序后的最后一条
Last()
//查询多条数据
Find()
一些技巧:
gorm存在内连条件,可以在first方法第二个参数传入表达式进行检索
可以用Find方法传入一个切片来查多个数据,Where方法同样适用于Find
当觉得返回的太杂的时候可以新建一个结构体,内装想要的字段,调用的时候放入find中即可,前面用Model来指定查询的地方
关系
一对一关系
在A结构体内有类型为uint的BID字段并拥有B类型的字段进行belong to关联
在B结构体内有A类型字段进行has one关联
一对多关系
关系中的处理操作
PreLoad
当查询的结构体与其他结构体进行关联时,使用预加载方法来使查询时能够查到关联的结构体消息,第一个参数时要预加载的结构体字段,第二个参数可以是字符串查询字段,或者跟一个函数用来执行更多操作,PreLoad第二个参数的查询只针对查询的那一层
Joins
只适用于一对一关系,在PreLoad中的第二个参数中声明一个接收和返回值类型都为*gorm.DB类型的函数,在函数体内执行Joins方法来加载其子成员,当想在关联的结构体中拿到被关联结构体中的一个数据作为条件时使用
Association
使用这个方法可以对结构体进行关联
db.Model(&d).Association("b").Append(&g)
其中,d为要进行关联的实例,b为目标关联对象的类型,g为目标关联对象的实例
Append
用来增加关联
Clear
用来清除所有关联
Delete
用来删除关联
事务
GORM对事务的策略
GORM中对于处理与数据相关的内容会默认采用事务的形式进行,这个策略是可以被关闭的(并不建议),详见官方文档
常用方法
Transaction
这个方法接收一个函数,这个函数接收一个*gorm.DB类型,返回一个存放错误信息的错误,可以在函数体内书写想要进行事务操作的语句
Begin&Commit&Rollback
这三个方法一般搭配使用,用Begin开始进行一段事务操作,用Commit来结束Begin开始的事务操作,在其中,可以用Rollback来回滚事务中的所有操作
SavePoint&RollbackTo
在事务中,可以用SavePoint去保存一个点,使用RollbackTo去回滚到这个点,而不会回滚全部的内容