GORM的简单使用 | 青训营笔记

109 阅读2分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第4篇笔记

1. 什么是ORM框架

ORM(Object Relational Mapping,对象关系映射),简单理解就是将面向对象语言的类与关系数据库中的关系的一种映射,并且将对关系型数据库的CRUD操作封装起来,方便开发者使用,其中GORM就是go语言的一个ORM框架。

2. 什么是DSN

DSN(Data Source Name,数据源名称),包含数据库的用户名,密码,连接方式,地址,端口号,数据库名称,字符集等等,一个简单的例子如下:

root:123456@tcp(localhost:3306)/dousheng?charset=utf8mb4&parseTime=True&loc=Local
  • charset=utf8mb4支持最完整的中英文字符集
  • parseTime=TrueMySQL中的DATEDATETIME等时间类型字段将自动转换为golang中的time.Time类型
  • loc=Local时区为服务器本地时区

3. GORM连接MySQL

var err error
MyDB, err = gorm.Open(mysql.Open(constants.MySQLDSN),
    &gorm.Config{
            PrepareStmt:            true,
            SkipDefaultTransaction: true,
        },
)
if err != nil {
    panic(err)
}
  • PrepareStmt 所有的操作都会创建并缓存预编译语句,以加速后续执行速度
  • SkipDefaultTransaction 跳过系统默认事务
  • DefaultStringSize string 类型字段的默认长度

4. 连接池

sqlDB, err := MyDB.DB()
if err != nil {
    panic(err)
}
sqlDB.SetMaxIdleConns(10)
sqlDB.SetMaxOpenConns(100)
  • SetMaxIdleConns 设置空闲连接池中连接的最大数量
  • SetMaxOpenConns 设置打开数据库连接的最大数量
  • SetConnMaxLifetime 设置了连接可复用的最大时间

5. 模型定义

GORM 倾向于约定,而不是配置。默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAtUpdatedAt 字段追踪创建、更新时间

GORM 定义一个 gorm.Model 结构体,其包括字段 IDCreatedAtUpdatedAtDeletedAt

// gorm.Model 的定义
type Model struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
}
  • 嵌入结构体
type User struct {
  gorm.Model
  Name string
}
// 等效于
type User struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
  Name string
}

对于正常的结构体字段,可以通过标签 embedded 将其嵌入

type Author struct {
    Name  string
    Email string
}

type Blog struct {
  ID      int
  Author  Author `gorm:"embedded"`
  Upvotes int32
}
// 等效于
type Blog struct {
  ID    int64
  Name  string
  Email string
  Upvotes  int32
}

6.简单的CRUD接口

  1. 创建记录
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}

result := db.Create(&user) // 通过数据的指针来创建

user.ID             // 返回插入数据的主键
result.Error        // 返回 error
result.RowsAffected // 返回插入记录的条数

// 批量插入
var users = []User{{Name: "jinzhu1"}, {Name: "jinzhu2"}, {Name: "jinzhu3"}}
db.Create(&users)
  1. 查找记录
MyDB.Where("name = ?", name).Find(&res)
MyDB.Where("id in ?", userIDs).Find(&res)
  1. 删除记录
MyDB.Where("user_id = ? AND video_id = ?", userID, videoID).Delete(&Favorite{})

使用 Unscoped 永久删除匹配的记录

db.Unscoped().Delete(&order)
// DELETE FROM orders WHERE id=10;
  1. 更新记录
tx := MyDB.WithContext(ctx)
tx.Model(&User{}).Where("ID = ?", followID).Update("follower_count", gorm.Expr("follower_count + ?", 1))
tx.Model(&User{}).Where("ID = ?", followerID).Update("follow_count", gorm.Expr("follow_count + ?", 1))