GORM 超详细总结
1. GORM 简介
GORM 是 Go 语言的一个 ORM (Object-Relational Mapping) 库,全称为 Go ORM。它提供了友好的 API 来操作数据库,支持多种数据库(MySQL、PostgreSQL、SQLite、SQL Server 等)。
主要特性:
-
全功能 ORM
-
关联 (Has One, Has Many, Belongs To, Many To Many, Polymorphism)
-
钩子 (Before/After Create/Save/Update/Delete/Find)
-
预加载
-
事务
-
复合主键
-
SQL 构建器
-
自动迁移
-
日志
-
可扩展的插件系统
-
每个特性都有测试覆盖
2. 安装与配置
安装:
go get -u gorm.io/gorm go get -u gorm.io/driver/mysql # 或其他数据库驱动
基本配置:
import (
"gorm.io/gorm"
"gorm.io/driver/mysql"
)
func main() {
dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// 迁移 schema
db.AutoMigrate(&Product{})
}
3. 模型定义
基本模型:
type User struct {
gorm.Model
Name string
Email *string
Age uint8
Birthday *time.Time
MemberNumber sql.NullString
ActivatedAt sql.NullTime
}
gorm.Model:
type Model struct {
ID uint `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
字段标签:
type User struct {
Name string `gorm:"type:varchar(100);uniqueIndex"`
Age int `gorm:"default:18"`
}
常用标签:
-
primaryKey- 主键 -
column- 指定列名 -
type- 列数据类型 -
size- 列大小 -
default- 默认值 -
not null- 非空 -
unique- 唯一 -
uniqueIndex- 唯一索引 -
index- 普通索引 -
check- 检查约束 -
<-- 字段权限(create, update) -
->- 字段权限(read) -
-- 忽略字段
4. CRUD 操作
创建记录:
user := User{Name: "Jinzhu", Age: 18}
result := db.Create(&user) // 通过数据的指针来创建
user.ID // 返回插入数据的主键
result.Error // 返回 error
result.RowsAffected // 返回插入记录的条数
批量创建:
var users = []User{{Name: "jinzhu1"}, {Name: "jinzhu2"}, {Name: "jinzhu3"}}
db.Create(&users)
查询记录:
单条查询:
// 获取第一条记录(主键升序) db.First(&user) // SELECT * FROM users ORDER BY id LIMIT 1; // 获取一条记录,没有指定排序字段 db.Take(&user) // SELECT * FROM users LIMIT 1; // 获取最后一条记录(主键降序) db.Last(&user) // SELECT * FROM users ORDER BY id DESC LIMIT 1; result := db.First(&user) result.RowsAffected // 返回找到的记录数 result.Error // returns error or nil
条件查询:
// 获取第一条匹配的记录
db.Where("name = ?", "jinzhu").First(&user)
// SELECT * FROM users WHERE name = 'jinzhu' ORDER BY id LIMIT 1;
// 获取所有匹配的记录
db.Where("name <> ?", "jinzhu").Find(&users)
// SELECT * FROM users WHERE name <> 'jinzhu';
// IN
db.Where("name IN ?", []string{"jinzhu", "jinzhu 2"}).Find(&users)
// SELECT * FROM users WHERE name IN ('jinzhu','jinzhu 2');
// LIKE
db.Where("name LIKE ?", "%jin%").Find(&users)
// SELECT * FROM users WHERE name LIKE '%jin%';
// AND
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)
// SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;
// 主键查询
db.First(&user, 10)
// SELECT * FROM users WHERE id = 10;
更新记录:
// 更新单个字段
db.Model(&user).Update("name", "hello")
// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111;
// 更新多个字段
db.Model(&user).Updates(User{Name: "hello", Age: 18})
// UPDATE users SET name='hello', age=18, updated_at='2013-11-17 21:34:10' WHERE id=111;
// 使用 map 更新多个字段
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18})
删除记录:
// 删除一条记录
db.Delete(&user)
// DELETE FROM users WHERE id = 10;
// 带条件的删除
db.Where("name = ?", "jinzhu").Delete(&user)
// DELETE FROM users WHERE name = 'jinzhu';
// 批量删除
db.Delete(&User{}, "name LIKE ?", "%jinzhu%")
// DELETE FROM users WHERE name LIKE '%jinzhu%';
5. 高级查询
预加载:
type User struct {
gorm.Model
Name string
Orders []Order
}
type Order struct {
gorm.Model
UserID uint
Price float64
}
// 预加载 Orders
db.Preload("Orders").Find(&users)
// SELECT * FROM users;
// SELECT * FROM orders WHERE user_id IN (1,2,3,4);
// 嵌套预加载
db.Preload("Orders.OrderItems").Find(&users)
关联查询:
var user User
db.First(&user)
var orders []Order
db.Model(&user).Association("Orders").Find(&orders)
作用域:
func AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
return db.Where("amount > ?", 1000)
}
func PaidWithCreditCard(db *gorm.DB) *gorm.DB {
return db.Where("pay_mode = ?", "card")
}
db.Scopes(AmountGreaterThan1000, PaidWithCreditCard).Find(&orders)
// 查找所有金额大于 1000 且使用信用卡支付的订单
原生 SQL:
db.Raw("SELECT id, name FROM users WHERE name = ?", "jinzhu").Scan(&result)
db.Exec("DROP TABLE users")
6. 事务
自动事务:
db.Transaction(func(tx *gorm.DB) error {
// 在事务中执行一些 db 操作
if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
// 返回任何错误都会回滚事务
return err
}
if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
return err
}
// 返回 nil 提交事务
return nil
})
手动事务:
// 开始事务
tx := db.Begin()
// 在事务中执行一些 db 操作
if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
tx.Rollback()
return
}
if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
tx.Rollback()
return
}
// 提交事务
tx.Commit()
7. 钩子(Hooks)
GORM 提供了以下钩子:
-
BeforeSave
-
BeforeCreate
-
AfterCreate
-
BeforeUpdate
-
AfterUpdate
-
BeforeDelete
-
AfterDelete
-
AfterFind
示例:
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
u.UUID = uuid.New()
return
}
8. 性能优化
禁用默认事务:
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
SkipDefaultTransaction: true,
})
批量插入:
var users = []User{{Name: "jinzhu1"}, {Name: "jinzhu2"}, {Name: "jinzhu3"}}
db.CreateInBatches(users, 100)
查询优化:
// 只查询需要的字段
db.Select("name", "age").Find(&users)
// 使用 Pluck 获取单列
var ages []int64
db.Model(&User{}).Pluck("age", &ages)
9. 错误处理
GORM 的错误处理:
if err := db.Where("name = ?", "jinzhu").First(&user).Error; err != nil {
// 处理错误
if errors.Is(err, gorm.ErrRecordNotFound) {
// 记录未找到
} else {
// 其他错误
}
}
10. 扩展功能
自定义数据类型:
type JSON json.RawMessage
// 实现 Scanner 和 Valuer 接口
func (j *JSON) Scan(value interface{}) error {
// 实现扫描逻辑
}
func (j JSON) Value() (driver.Value, error) {
// 实现值逻辑
}
插件开发:
GORM 提供了插件系统,可以开发自定义插件扩展功能。
11. 常见问题
1. 如何关闭日志?
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Silent),
})
2. 如何处理软删除?
// 模型包含 gorm.DeletedAt 字段
db.Unscoped().Where("age = 20").Find(&users)
// 查询时会忽略 deleted_at IS NULL 条件
db.Unscoped().Delete(&order)
// 永久删除
3. 如何添加表前缀?
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
NamingStrategy: schema.NamingStrategy{
TablePrefix: "t_", // 表前缀
},
})
12. 最佳实践
-
模型设计:
-
使用结构体标签定义字段属性
-
合理设计关联关系
-
考虑使用软删除
-
-
查询优化:
-
只查询需要的字段
-
合理使用预加载
-
使用批量操作减少数据库交互
-
-
错误处理:
-
总是检查错误
-
区分不同类型的错误(记录未找到、连接错误等)
-
-
事务管理:
-
对需要原子性操作的使用事务
-
避免长事务
-
-
性能监控:
-
使用 GORM 的调试模式检查生成的 SQL
-
监控慢查询
-
GORM 是一个功能强大且灵活的 ORM 库,通过合理使用可以大大提高 Go 语言开发中数据库操作的效率和可维护性。
👉 立即点击链接,开启你的全栈开发之路:Golang全栈开发完整课程
2374

被折叠的 条评论
为什么被折叠?



