这是我参与「第三届青训营 -后端场」笔记创作活动的第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将删除模型的所有记录