Gorm入门 | 青训营笔记

108 阅读6分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 13 天

前言

大家好呀,这是我参加青训营伴学笔记创作活动的第 13 天,如存在问题,烦请各位斧正!

其中有一些关键图片超过了最大字符限制,不能上传了,我都使用特殊标记给它标记出来了,如有需要,请联系我。

入门使用

概述

1)ORM:Object Relational Mapping(对象关系映射):

即在golang中,自定义的一个结构体对应着一张表,结构体的实例则对应着表中的一条记录。

2)安装:go get github.com/jinzhu/gorm

声明模型

采用约定优于配置原则:

1)模型名和表名的映射规则:首字母变小写、尾部加复数,多个值会变为下划线连接:

(1)举例:User => users UserInfo => user_infos

(2)db.SingularTable(true) 让grom转义struct名字的时候不用加上s

2)数据模型:

type User struct {
        Id  int
        Name string
        Age  int
}

3)嵌套:也可以抽取出公共元素放到Model,然后让User有Model属性,就相当于有了公共元素作为属性。

4)结构体字段名和列名的对应规则

CreatedTime --> create_time

可以通过gorm标签指定列名,AnimalId int64 gorm:"column:beast_id"

连接数据库

// 用户名:密码@tcp(ip:port)/数据库?charset=utf8mb4&parseTime=True&loc=Local
dsn := "root:a1134443466@tcp(127.0.0.1:3306)/property?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn),
&gorm.Config{})
if err != nil {
        panic(err)
}

1)注意:parseTime是查询结果是否自动解析为时间。+loc是MySQL的时区设置

2)可以通过传入参数实现缓存预编译语句来提高效率:&gorm.Config{

PrepareStmt: true }

定义模型进阶

在默认表名上加其他规则

1)在默认表名前加sys_前缀

gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string  {
return  "sys_" + defaultTableName;
}

2)自定义表名:

func (模型) TableName() string{
    return "新的表名"
}

gorm.Model

1)基本模型定义gorm.Model,包括字段ID,CreatedAt,UpdatedAt,DeletedAt

type Model struct {
        ID       uint `gorm:"primarykey"`
        CreatedAt   time.Time
        UpdatedAt   time.Time
        DeletedAt   DeletedAt `gorm:"index"`
}

只需要在自己的模型中指定gorm.Model匿名字段,即可使用上面的四个字段

type User struct {
gorm.Model
Name string
}

结构体标签gorm的使用

type User struct {

  Name string `gorm:"<-:create"` // 允许读和创建

  Name string `gorm:"<-:update"` // 允许读和更新

  Name string `gorm:"<-"`        // 允许读和写(创建和更新)

  Name string `gorm:"<-:false"`  // 允许读,禁止写

  Name string `gorm:"->"`        // 只读(除非有自定义配置,否则禁止写)

  Name string `gorm:"->;<-:create"` // 允许读和写

  Name string `gorm:"->:false;<-:create"` // 仅创建(禁止从 db 读)

  Name string `gorm:"-"` 
// 读写操作均会忽略该字段

}

创建/更新时间追踪(纳秒、毫秒、秒、Time)

1)GORM 约定使用 CreatedAt、UpdatedAt 追踪创建/更新时间。如果您定义了这种字段,GORM 在创建、更新时会自动填充 当前时间。

2)要使用不同名称的字段,您可以配置 autoCreateTim、autoUpdateTim 标签

如果您想要保存 UNIX(毫/纳)秒时间戳,而不是 time,您只需简单地将 time.Time 修改为 int 即可:

type User struct {
 
CreatedAt time.Time // 在创建时,如果该字段值为零值,则使用当前时间填充
 
UpdatedAt int       // 在创建时该字段值为零值或者在更新时,使用当前时间戳秒数填充
 
Updated   int64 `gorm:"autoUpdateTime:nano"` // 使用时间戳填纳秒数充更新时间
 
Updated   int64 `gorm:"autoUpdateTime:milli"` // 使用时间戳毫秒数填充更新时间
 
Created   int64 `gorm:"autoCreateTime"`      // 使用时间戳秒数填充创建时间

}

字段标签

声明 model 时,tag 是可选的,GORM 支持以下 tag: tag 名大小写不敏感:

多个属性值之间用分号分隔(英文的;):gorm:"size:64;not null"

标签名 说明

column:指定db列名列数据类型,推荐使用兼容性好的通用类型,例如:所有数据库都攴持bool、int、uint、float, string、time、 bytes并且可以和其他标签一起使用,例如: not null、size,autoincrement.像 varbinary(8)这样指定数据库数据类型也是支持的。

在使用指定数据库数据类型时,它需要是完整的数据库数据类型,如: MEDIUMINT UNSIGNED not NULLAUTO INSTREMENT

size:指定列大小,例如:size:256primarykey指定列为主键指定列为唯default指定列的默认值precision指定列的精度scale指定列大指定列为 NOT NULLautoincrement指定列为自动增长embedded嵌套字段

embedded Prefix嵌入字段的列名前缀时追踪当前时nt字段,它会追踪时间戳秒数nano/ mill来追踪纳auto

create time亳秒时间戳,例如: autocreate Time:nano创建更新时追踪当前时间,对于int字段,它会追踪时间戳秒数,您可以使用nano/m来追auto

update Time踪纳秒、亳秒时间戳,例如: autoupdate Time:mindex根据参数创建索引,多个字段使用相同的名称则创建复合索引,查看索引获取详

uniqueindexndex相同建的是唯一索chec创建检查约束,例如 check:age>13,查看约束获取详设置字段写入的权限,<-: create只仓date只更新、< false无写入权限、<创建和更新权限字段读的权限,->fase无读权限忽略该字段,-无读写权

order by优化

1、MySQL的排序,有两种方式:

1)Using filesort : 通过表的索引或全表扫描,读取满足条件的数据行,然后在排序缓冲区sortbuffer中完成排序操作,

所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序。

2)Using index : 通过有序索引顺序扫描直接返回有序数据,这种情况即为 using index,不需要额外排序,操作效率高。

3)对于以上的两种排序方式,Using index的性能高,而Using filesort的性能低,我们在优化排序操作时,尽量要优化为 Using index。

4)使用explain可以查看执行计划中的Extra字段是上述两者中的哪一种。

2、优化

1)假如要根据字段进行降序排序,但是此时Extra中出现了 Backward index scan,这个代表反向扫描索引,因为在MySQL中我们创建的索引,

默认索引的叶子节点是从小到大排序的,而此时我们查询排序时,是从大到小,所以,在扫描时,就是反向扫描,就会出现 Backward index scan。

在MySQL8版本中,支持降序索引,我们也可以创建降序索引。

2)创建索引时,如果未指定顺序,默认都是按照升序排序的,而查询时,一个升序,一个降序,此时 就会出现Using filesort。

创建联合索引时,可以让两个字段有不同的升降序:create index idx_user_age_phone_ad on tb_user(age asc ,phone desc);

3)其他优化原则:

(1)根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则。

(2)尽量使用覆盖索引。

(3)如果不可避免的出现filesort,大数据量排序时,可以适当增大排序缓冲区大小sort_buffer_size(默认256k)。