GORM | 豆包MarsCode AI刷题

54 阅读3分钟

GORM

简介

gorm是一个强大的Go编程语言中的ORM(对象关系映射)库。ORM是一种技术,它将数据库表中的数据映射到面向对象的模型中,从而简化了数据库操作。

常见操作

下面将以User结构体为例展示常见操作,User结构体定义如下:

type User struct {
    user_id int
    email string
    passwd string
}

连接数据库

连接数据库使用dsn语句,连接MySQL数据库的代码如下:

import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

func main() {
  dsn := "user:passwd@tcp(localhost:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
}

其中需要关注的主要有user,passwd和localhost,三者分别指定连接MySQL数据库的用户名、密码、数据库地址。

添加数据

// 单条记录
user := User{Name: "zzz"}
result := db.Create(&user)

//多条记录
users := []*User{
    {Name: "bbb", Email;: "bbb@example.com"},
    {Name: "ccc"},
}
result := db.Create(users)

修改数据

修改数据时,单列更新使用Update、多列使用Updates,下面仅展示单列更新

// 根据条件更新数据
db.Model(&User{}).Where("Name = ?", "zzz").Update("Email", "zzz@example.com")

// 根据结构体更新,gorm将使用user结构体的非零值字段作为查询条件
db.Model(&user).Update("Email", "zzz@example.com")

// 根据条件和结构体更新
db.Model(&user).Where("Name = ?", "zzz").Update("Email", "zzz@example.com")

删除数据

Gorm支持通过主键删除数据,如下

// 删除主键为10的用户
db.Delete(&User{}, 10)

// 删除主键为10的用户
db.Delete(&User{}, "10")

// 删除主键为1、2、3的用户
db.Delete(&users, []int{1,2,3})

// 按照结构体删除
db.Delete(&user)

// 按照条件和结构体删除
db.Where("Name = ?", "zzz").Delete(&user)

需要注意,按照结构体删除时若未指定主键,将触发批量删除

gorm也提供了软删除功能,主要是通过在结构体定义中添加Deleted gorm.DeletedAt实现的。

Unscoped被用于在查询时查询到软删除的数据,并在删除时彻底删除数据

db.Unscoped().Where("Name = zzz").Find(&users)
db.Unscoped().Delete(&user)

查询数据

// 单条查询
db.Find(&users, User{Name: "zzz"})

// 批量查询
db.Where("Name = ?", "admin").Find(&users)

查询数据时First如果未查到会直接panic。推荐使用批量查询,批量查询若查询不到结果为空,可以借此实现异常处理。

事务

在事务的实现方式上,Gorm提供了手动事务和自动事务两种。

手动事务中用户需要手动Rollback、Commit等函数手动实现事务功能。

自动事务:在函数中返回err时、程序会自动调用Rollback回滚事务;当函数结束时,程序会自动调用Commit提交事务。

钩子

钩子(Hook) 是在创建、查询、更新、删除等操作之前、之后调用的函数。

Gorm为创建、查询、删除操作提供的钩子函数如下:

  1. Create
    1. BeforeSave:在保存数据前执行的钩子函数
    2. BeforeCreate:在创建前执行的钩子函数
    3. AfterCreate:在创建后执行的钩子函数
    4. AfterSave:在保存数据后执行的钩子函数
  2. Update
    1. BeforeSave:同Create.BeforeSave
    2. BeforeUpdate:在更新前执行的钩子函数
    3. AfterUpdate:在更新后执行的钩子函数
    4. AfterSave:同Create.AfterSave
  3. Delete
    1. BeforeDelete:在删除前执行的钩子函数
    2. AfterDelete:在删除后执行的钩子函数

Gorm中保存、删除操作默认运行在事务上,如果钩子函数返回了错误,对数据库的修改将会被回滚。

思考

在秒杀场景下,为了保证高性能,可以设置仅存储订单数量、商品id的专门数据表,通过缩小数据表大小加快处理速率。 在秒杀活动中,可以考虑反范式化避免超卖等情况,比如将deal_id、buy_count和max_count放在同一个表内,通过一条语句实现原子性操作:

UPDATE SET buy_count = buy_count + 1 WHERE deal_id = ? AND buy_count + 1 < max_count