GROM笔记 | 青训营笔记

344 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第4篇笔记

GORM介绍

介绍

Object-Relationl Mapping,即对象关系映射,这里的Relationl指的是关系型数据库 它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了。 Golang写的,GitHub上活跃度很高的orm库

特点

  • 全功能ORM;
  • 关联(包含一个,包含多个,属于,多对多,多种包含);
  • Callbacks(创建/保存/更新/删除/查找之前/之后);
  • 预加载;
  • 事务
  • 复合主键
  • SQL Builder
  • 自动迁移
  • 日志
  • 可扩展,编写基于GORM回调的插件
  • 每个功能都有测试
  • 开发人员友好

安装

go get github.com/ jinzhu/gorm

模型定义

与使用 Go 标准库 sql 包操作数据库表相同,使用 GORM 操作数据库,也需要先声明模型,模型一般是基于 Go 语言的基础数据类型、实现了 Scanner 和 Valuer 接口的自定义类型,以及它们的指针或别名。 模型名和表名的映射关系 规则

  • 第一个大写字母变为小写;
  • 遇到其他大写字母变为小写并且在前面加下划线;
  • 连着的几个大写字母,只有第一个遵循上面的两条规则,其他的大写字母转为小写,不加下划线,遇到小写,前面的第一个大写字母变小写并加下划线;
  • 复数形式;

示例代码:

type User struct {
  ID           uint
  Name         string
  Email        *string
  Age          uint8
  Birthday     *time.Time
  MemberNumber sql.NullString
  ActivedAt    sql.NullTime
  CreatedAt    time.Time
  UpdatedAt    time.Time
}
约定优于配置
  • 表名为struct name的snake_ cases 复数格式
  • 字段名为field name的snake_ case 单数格式
  • ID/ld字段为主键,如果为数字,则为自增主键
  • CreatedAt字段,创建时,保存当前时间
  • UpdatedAt字段,创建、更新时,保存当前时间
  • gorm.DeletedAt字段,默认开启soft delete模式

约束

默认情况下,GORM 约定使用 ID 作为主键,使用结构体名的复数作为表名,字段名作为列名,使用 CreatedAt、UpdatedAt、DeletedAt时间追踪。如果约定与需求不符,可以自定义配置。GORM 定义了一个 gorm.Model 结构体,字段包括 ID、CreatedAt、UpdatedAt、DeletedAt,我们可以将它嵌入到我们自定义的结构体中.

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

使用

获取数据库连接

用户名:密码:@tcp(域名:端口)/数据库?参数

func getConnect() *gorm.DB {
   db, err := gorm.Open(mysql.Open("root:123456@tcp(39.105.196.187:3306)/test?parseTime=true"))
   if err != nil {
      fmt.Println(err)
      return nil
   }
   return db

}

增加

user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
db.NewRecord(user) // => 返回 `true` ,因为主键为空
db.Create(&user)
db.NewRecord(user) // => 在 `user` 之后创建返回 `false`

然后 SQL 会排除那些没有值或者有 零值 的字段,在记录插入数据库之后,gorm将从数据库中加载这些字段的值。 意 所有包含零值的字段,像 0''false 或者其他的 零值 不会被保存到数据库中,但会使用这个字段的默认值。你应该考虑使用指针类型或者其他的值来避免这种情况。

查询

// 获取第一条匹配的记录
db.Where("name = ?", "jinzhu").First(&user)
//// SELECT * FROM users WHERE name = 'jinzhu' limit 1;

// 获取所有匹配的记录
db.Where("name = ?", "jinzhu").Find(&users)
//// SELECT * FROM users WHERE name = 'jinzhu';

具体查哪张表是根据你传入的结构体决定的,所以结构体名称必须和数据库对应,如果数据库中是下划线命名,结构体就转换成驼峰的形式,如:user_info为表名时,结构体名称应该为UserInfo。这里的Find(&user)还有一个作用就是把结果绑定至user中,所以这里一定要用指针作为参数传入。

更新

//更新某个字段
db .ModeL(&product) , Update("Price",2000)
db .ModeL(&product) . UpdateColumn("Price",2000) 
//更新多个字段
db .Model(&product). Updates(Product{Price: 2000, Code: "L1212"})
db .Model(&product) . updates(map[ string]interface{}{"Price": 2000, "Code": "L1212"})
//批量更新
db .Model(&Product{}). Where("price <?",2000).Updates(map[stringJinterfacef{"Price": 2000})

如果您只想在更新时更新或忽略某些字段,可以使用Select, Omit

删除

//需要使用GORMMigrate数据库迁移数据库外键才行
db . AutoMigrate(&User{})
//如果未启用软删除,在删除User时会白动删除其依赖
db . DeleteC&User{})
//方法2:使用Select实现级联删除,不依赖数据库约束及软删除
//删除user时,也删除user的account
db. Select(" Account"). Delete(&user)
//删除user时,也删除用户及其依赖的所有has one/many. many2many记录
db.Select( clause . Associations).Delete(&user)

删除记录时,需要确保其主要字段具有值,GORM将使用主键删除记录,如果主要字段为空,GORM将删除模型的所有记录