Gorm 是一个用于 Go 语言的 ORM(对象关系映射)库,它提供了一种简单且强大的方式来操作数据库。它支持多种数据库,包括 MySQL、PostgreSQL、SQLite 和 SQL Server 等。同时支持可以复用或自行开发驱动。
Gorm的安装
go get -u gorm.io/gorm
go get -u gorm.io/driver/sqlite
Gorm的约定(默认)
- Gorm 使用名为ID的字段作为主键
- 使用结构体的蛇形复数作为表名
- 字段名的蛇形作为列名
- 使用CreatedAt、UpdatedAt字段作为创建、更新时间
gorm.Model 定义
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
产品结构体定义
type Product struct {
gorm.Model
Code string
Price uint
}
// 等价于
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
Code string
Price uint
}
数据库的连接
import (
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
func main() {
// 连接数据库为Mysql
dsn := "usr:pwd@tcp(127.0.0.1:3306)/go_demo_db?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: logger.Default.LogMode(logger.Info)})
if err != nil {
panic("failed to connect database")
}
}
Gorm创建一条数据
// Create
db.Create(&Product{Code: "I42", Price: 500})
Gorm查询数据
使用First查询时:
注意:First的使用
使用 First 时, 需要注意查询不到数据会返回 ErrRecordNotFound。使用 Find 查询多条数据, 查询不到数据不会返回错误。
使用结构体作为查询条件:
当使用结构作为条件查询时, GORM只会查询非零值字段。 这意味着如果您的字段值为 0、 ''、 false 或其他 零值,该字段不会被用于构建查询条件, 使用Map 来构建查询条件。
// Read
var product Product
db.First(&product, 1) // 根据整形主键查找
db.First(&product, "code = ?", "D42") // 查找 code 字段值为 D42 的记录
Gorm更新数据
使用 Struct 更新时, 只会更新非零值, 如果需要更新零值可以使用 Map 更新或使用Select 选择字段。
// Update - 将 product 的 price 更新为 200
db.Model(&product).Update("Price", 200)
// Update - 更新多个字段
db.Model(&product).Updates(Product{Price: 200, Code: "H42"}) // 仅更新非零值字段
db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "H42"})
Gorm删除数据
Gorm删除数据分为物理删除和软删除:
- 物理删除:物理删除是指直接从数据库中删除数据,完全清除该记录。在Gorm中,可以使用
Delete方法来进行物理删除操作。 - 软删除:软删除是指在数据库中保留被删除数据的记录,但标记为已删除。在Gorm中,可以通过添加一个字段来标记删除状态,通常命名为
DeletedAt,并使用Delete方法进行软删除。使用 Unscoped 可以查询到被软删的数据。
// Delete - 删除 product
db.Delete(&product, 1)
Gormc常见的字段标签
| 标签名 | 示例 | 说明 |
|---|---|---|
| column | gorm:"column:user_id" | 指定db列名 |
| size | gorm:"size: 256" | 定义列数据类型的大小或长度 |
| primaryKey | gorm:"column:user_id;primaryKey" | 主键 |
| default | gorm:"column:status;default:0" | 默认值 |
| not null | gorm:"not null" | 不为空 |
| autoIncrement | gorm:"autoIncrement" | 自动增长 |
| index | gorm:"index" | 根据参数创建索引,多个字段使用相同的名称则创建复合索引 |
| unique | gorm:"columun:user_id;unique" | 唯一键 |
| - | gorm:"-:all"/gorm:"-:migration" | 忽略该字段,- 表示无读写,-:migration 表示无迁移权限,-:all 表示无读写迁移权限 |
| comment | gorm:"comment:'用户名'" | 迁移时为字段添加注释 |
| embedded | gorm:"embeded" | 嵌套字段 |
后续未完,抽空补😭
// 代码示例
package main
import (
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
type Product struct {
gorm.Model
Code string
Price uint
}
func main() {
dsn := "root:abc123@tcp(127.0.0.1:3306)/go_demo_db?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{Logger: logger.Default.LogMode(logger.Info)})
if err != nil {
panic("failed to connect database")
}
// 迁移 schema
db.AutoMigrate(&Product{})
// Create
db.Create(&Product{Code: "I42", Price: 500})
// Read
var product Product
db.First(&product, 1) // 根据整形主键查找
db.First(&product, "code = ?", "D42") // 查找 code 字段值为 D42 的记录
// fmt.Println(res.RowsAffected)
// Update - 将 product 的 price 更新为 200
db.Model(&product).Update("Price", 200)
// // Update - 更新多个字段
db.Model(&product).Updates(Product{Price: 200, Code: "H42"}) // 仅更新非零值字段
db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "H42"})
// // Delete - 删除 product
db.Delete(&product, 1)
}