这是我参与「第五届青训营 」伴学笔记创作活动的第 12 天
Gorm -> The fantastic ORM library for Golang aims to be developer friendly.
本文介绍V2版本的使用
安装和导入
使用MySQL数据库
$ go get -u gorm.io/gorm
$ go get -u gorm.io/driver/mysql
import(
"gorm.io/driver/mysql"
"gorm.io/gorm"
"fmt"
)
目前 Gorm 支持MySQL、SQLServer、PosrgreSQL、SQLite数据库,若需使用其他数据库,需下载和导入不同的驱动或自行开发驱动
基本使用
Gorm 支持 Migration 特性,支持根据 Go Struct 结构自动生成对应的表结构。
定义Grom Model
gorm.Model 是一个包含一些基本字段的结构体, 包含的字段有 ID,CreatedAt, UpdatedAt, DeletedAt。可以用它来嵌入到结构体中
type Product struct {
gorm.Model
ID uint
Code string
Price uint
}
Gorm 默认使用ID字段作为主键,使用结构体的蛇形复数作为表名(即 type Product struct {} 默认表名是products)
如果设置禁用表名复数形式属性为 true,Product 的表名将是 product
db.SingularTable(true)
使用字段名的蛇形作为列名(或者使用 column 字段重写列名),并使用 CreatedAt,UpdatedAt 字段追踪创建和更新时间
可以使用 default 标签为字段定义默认值
type Product struct {
gorm.Model
ID uint `gorm:"primarykey"
Code string `gorm:"default:A"`
Price uint `gorm:"default:0"`
}
还可以使用标签控制字段级别的权限
为model定义表名
如果不使用结构体复数作为表名,还可以设置为其他的
func (p Product) TableName() String {
return "product"
}
连接数据库
db, err := gorm.Open(
mysql.Open("username:password@tcp(localhost:3306)/dbname?charset=utf8"),
&gorm.Config(){})
if err != nil {
panic("fail to connect database")
}
建表
通过 AutoMigrate() 快速建表,如果表已经存在不会重复创建
// 根据 Product 结构体,自动创建表结构.
db.AutoMigrate(&Product{})
或者使用 Schema 方法
- 检查表是否存在
// 检测Product结构体对应的表是否存在
db.Migrator().HasTable(&Product{})
// 检测表名product是否存在
db.Migrator().HasTable("product")
- 建表
// 根据Product结构体建表
db.Migrator().CreateTable(&Product{})
- 删除表
// 删除Product结构体对应的表
db.Migrator().DropTable(&Product{})
// 删除表名为product的表
db.Migrator().DropTable("product")
创建数据
创建单条数据
db.Create(&Product{Code: "ABC", Price: 100})
p := &Product{Code: "DE"}
res := db.Create(p)
fmt.Println(res.err)
fmt.Println(res.ID)
还可使用clause.OnConflict处理数据冲突
p := &Product{Code: "DE", ID: 2}
db.Clause(clause.OnConflict{DoNothing: true}).Create(&p)
创建多条数据
products := []*Product{{Code: "FG", Price: 888}, {Code: "H"}}
res := db.Create(products)
fmt.Println(res.err)
for _, p := range products {
fmt.Println(p.ID)
}
查询数据
按照主键升序获取第一条记录,First()查询不到数据返回ErrRecordNotFound
var product Product
db.First(&product)
db.Last(&product)
使用结构体查询多条数据,Find()查询不到数据不会返回错误
products := &Product{}
result := db.Where("price > 500").Find(&products)
//相当于 SELECT * FROM product WHERE price > 500;
fmt.Println(result.RowsAffected)
fmt.Println(result.Error)
db.Where(&Product{Code: "H", Price: 0}).Find(&products)
当使用结构体作为查询条件时,Gorm 只会查询非零字段。若字段值为0、false或者其他零值,该字段不会被用于构建查询条件,而使用Map可以构建条件
使用Map查询
db.Where(map[string]interface{}{"Code": "ABC", "Price": 100}).Find(&products)
也可以使用 IN LIKE AND OR 等关键字
更新数据
使用结构体更新只会更新非零值
db.Model(&product).Update("Price", 300)
db.Model(&product).Updates(Product{Price: 300, Code: "FG"})
使用Save()会默认更新该对象的所有字段,即使你没有赋值
var product Product
db.Debug().Last(&product)
fmt.Printf("product: %#v",product)
product.Code = "AAA"
product.Price = 1000 s
db.Debug().Save(&product) //会更新所有的字段
使用Map或者Select()可以更新零值
db.Model(&product).Updates(map[string]interface{}{"Price": 500, "Code": "HIJK"})
删除数据
硬删除
db.Delete(&product,1)
db.Delete(&product, []int{1,2,3})
软删除
如果模型包含了一个 gorm.deletedat 字段(gorm.Model 已经包含了该字段),它将自动获得软删除的能力!
记录不会被从数据库中真正删除,但 Gorm 会将 DeletedAt 置为当前时间。且正常的查询方法查询不到该记录
使用Unscoped可以查询到被软删除的数据
db.Unscoped().Where("price = 100").Find(&products)
也可以使用 Unscoped 永久删除匹配的记录
Gorm 事务
Begin() Commit() Rollback()
tx := db.Begin()
if err = tx.Create(&Product{Code: "IJK"}).Error; err != nil {
tx.Rollback()
return
}
tx.Commit()
或者使用Transaction()自动提交事务,避免漏写Commit()
if err = db.Transaction(func(tx *gorm.DB) error {
if err = tx.Create(&Product{Code: "LMN"}).Error; err != nil {
return err
}
return nil
}); err != nil {
return
}
Gorm Hook
在创建、查询、更新、删除等操作前后自动调用的函数
Gorm允许用户自定义 BeforeSave, BeforeCreate, AfterSave, AfterCreate 等
若任何Hook返回错误,Gorm将停止后续操作并回滚事务
使用原生SQL
原生查询
var product Product
db.Raw("SELECT ID, code, price FROM product WHERE code = ?", "AAA").Scan(&product)
Exec 原生SQL
db.Exec("DROP TABLE product")
db.Exec("UPDATE product SET price = ? WHERE code = ?", gorm.Expr("price * ? + ?", 10, 500), "DE")
如果想更系统的学习Gorm的使用,还是看官网的文档比较好❤👌
参考资料
Go 框架三件套详解.pptx - 飞书云文档 (feishu.cn)
关于镜像 | 前言 |《GORM 中文文档 v2》| Go 技术论坛 (learnku.com)
GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.