这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天
Gorm介绍
GORM是一个神奇的,对开发人员友好的 Golang ORM 库
GORM安装
// 安装GORM
go get -u gorm.io/gorm
// 安装数据库驱动,这里以mysql为例
go get -u gorm.io/driver/mysql
GORM连接数据库
-
GORM目前支持MySQL,SQLserver,PostgreSQL,SQLite
-
GORM通过驱动来连接数据库,例如:
package main import ( "gorm.io/gorm" "gorm.io/driver/mysql" ) // 定义gorm model type Product struct { Code string Price uint } // 为model定义表名 func (p Product) TableName() string { return "product" } func main() { // 链接数据库 db, err := gorm.Open( mysql.Open("username:password@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local")) if err != nil { panic("failed to connect database") } // Create db.Create(&Product{Code: "D42", Price: 100}) } -
GORM 使用 database/sql 维护连接池
sqlDB, err := db.DB() // SetMaxIdleConns 设置空闲连接池中连接的最大数量 sqlDB.SetMaxIdleConns(10) // SetMaxOpenConns 设置打开数据库连接的最大数量。 sqlDB.SetMaxOpenConns(100) // SetConnMaxLifetime 设置了连接可复用的最大时间。 sqlDB.SetConnMaxLifetime(time.Hour) -
GORM 允许通过一个现有的数据库连接来初始化
*gorm.DBimport ( "database/sql" "gorm.io/gorm" ) sqlDB, err := sql.Open("postgres", "mydb_dsn") gormDB, err := gorm.Open(postgres.New(postgres.Config{ Conn: sqlDB, }), &gorm.Config{})
GORM约定大于配置
-
GORM 使用
ID作为主键 -
使用结构体名的
蛇形复数作为表名 -
字段名的
蛇形作为列名(蛇形命名法:各个单词之间通过下划线“_”连接) -
使用
CreatedAt、UpdatedAt字段追踪创建、更新时间 -
修改约定的
CreatedAt、UpdatedAt字段填充数值类型,默认是time,可以修改成填充时间戳数type User struct { CreatedAt time.Time // 在创建时,如果该字段值为零值,则使用当前时间填充 UpdatedAt int // 在创建时该字段值为零值或者在更新时,使用当前时间戳秒数填充 Updated int64 `gorm:"autoUpdateTime:nano"` // 使用时间戳填纳秒数充更新时间 Updated int64 `gorm:"autoUpdateTime:milli"` // 使用时间戳毫秒数填充更新时间 Created int64 `gorm:"autoCreateTime"` // 使用时间戳秒数填充创建时间 } -
GORM 支持以下 tag语法: tag 名大小写不敏感,推荐使用小驼峰命名法
数据库CURD操作
创建
gorm支持结构体变量创建单一记录、切片批量创建记录、根据Map创建记录,指定字段创建记录
// 1.单一创建记录
user := User{Name: "Song", Age: 18, Birthday: time.Now()}
result := db.Create(&user) // 通过数据的指针来创建
user.ID // 返回插入数据的主键
result.Error // 返回 error
result.RowsAffected // 返回插入记录的条数
// 2.批量创建
var users = []User{{Name: "song11"}, {Name: "song22"}, {Name: "song33"}}
db.Create(&users)
// 创建后,回填主键的值
for _, user := range users {
user.ID // 1,2,3
}
// 3. 根据Map创建, 主键也不会回填
db.Model(&User{}).Create(map[string]interface{}{
"Name": "jinzhu", "Age": 18,
})
// batch insert from `[]map[string]interface{}{}`
db.Model(&User{}).Create([]map[string]interface{}{
{"Name": "jinzhu_1", "Age": 18},
{"Name": "jinzhu_2", "Age": 20},
})
// 3.指定字段创建
db.Select("Name", "Age", "CreatedAt").Create(&user)
// INSERT INTO `users` (`name`,`age`,`created_at`) VALUES ("name", 18, "2023-02-04 11:02:22.725")
db.Omit("Name", "Age", "CreatedAt").Create(&user)
// INSERT INTO `users` (`birthday`,`updated_at`) VALUES ("2023-01-01 00:00:00.000", "2023-02-04 11:05:21.775")
查询
-
查询单个记录:GORM 提供了
First、Last方法,没有找到记录时,它会返回ErrRecordNotFound错误// 获取第一条记录(主键升序) db.First(&user) // SELECT * FROM users ORDER BY id LIMIT 1; // 获取最后一条记录(主键降序) db.Last(&user) // SELECT * FROM users ORDER BY id DESC LIMIT 1; result.RowsAffected // 返回找到的记录数 result.Error // returns error // 检查 ErrRecordNotFound 错误 errors.Is(result.Error, gorm.ErrRecordNotFound) -
查询全部对象
// 获取全部记录 result := db.Find(&users) // SELECT * FROM users; result.RowsAffected // 返回找到的记录数,相当于 `len(users)` result.Error // returns error -
查询条件支持String,Struct,Map
更新
Save会保存所有的字段,即使字段是零值- 使用
Update更新单个列时,你需要指定条件,当使用了Model方法,且该对象主键有值,该值会被用于构建条件 - 更新多列,
Updates方法支持struct和map[string]interface{}参数
删除
-
删除一条记录时,使用
db.Delete删除对象需要指定主键,否则会触发批量删除 -
批量删除
db.Delete(&users, []int{1,2,3}) // DELETE FROM users WHERE id IN (1,2,3); -
软删除
-
如果数据库表包含了一个
gorm.deletedat字段,则自动获得软删除的能力 -
软删除能力的模型调用
Delete时,记录不会被从数据库中真正删除,GORM 会将DeletedAt置为当前时间标记已经删除的意思,默认为0 -
查看软删除记录
db.Unscoped().Where("age = 20").Find(&users) // SELECT * FROM users WHERE age = 20;
-
事务
- Gorm 提供了 Begin、Commit、Rollback 方法用于使用事务
- Gorm 提供了 Tansaction 方法用于自动提交事务,避免用户漏写 Commit、 Rollbcak。
Hook
- GORM 在 提供了 CURD 的 Hook 能力
- Hook 是在创建、查询、更新、删除等操作之前、之后自动调用的函数
- 如果任何 Hook 返回错误,GORM 将停止后续的操作并回滚事务
参考资料
《GORM 中文文档》 | Go 技术论坛 (learnku.com)
编程时常用命名规则(驼峰命名法、蛇形命名法、串式命名法)_Al资料站与复盘笔记的博客-CSDN博客_蛇形命名法
GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.
Go 框架三件套详解.pptx - 飞书云文档 (feishu.cn)