[ Golang ORM框架之GORM | 青训营笔记]

133 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天

Gorm介绍

GORM是一个神奇的,对开发人员友好的 Golang ORM 库

GORM安装

// 安装GORM
go get -u gorm.io/gorm
// 安装数据库驱动,这里以mysql为例
go get -u gorm.io/driver/mysql

GORM连接数据库

  1. GORM目前支持MySQL,SQLserver,PostgreSQL,SQLite

  2. GORM通过驱动来连接数据库,例如:

    package main
    
    import (
      "gorm.io/gorm"
      "gorm.io/driver/mysql"
    )
    
    // 定义gorm model
    type Product struct {
      Code  string
      Price uint
    }
    
    // 为model定义表名
    func (p Product) TableName() string {
        return "product"
    }
    
    func main() {
      // 链接数据库
      db, err := gorm.Open(
          mysql.Open("username:password@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local"))
      if err != nil {
        panic("failed to connect database")
      }
      // Create
      db.Create(&Product{Code: "D42", Price: 100})
    }
    
  3. GORM 使用 database/sql 维护连接池

    sqlDB, err := db.DB()
    
    // SetMaxIdleConns 设置空闲连接池中连接的最大数量
    sqlDB.SetMaxIdleConns(10)
    
    // SetMaxOpenConns 设置打开数据库连接的最大数量。
    sqlDB.SetMaxOpenConns(100)
    
    // SetConnMaxLifetime 设置了连接可复用的最大时间。
    sqlDB.SetConnMaxLifetime(time.Hour)
    
  4. GORM 允许通过一个现有的数据库连接来初始化 *gorm.DB

    import (
      "database/sql"
      "gorm.io/gorm"
    )
    
    sqlDB, err := sql.Open("postgres", "mydb_dsn")
    gormDB, err := gorm.Open(postgres.New(postgres.Config{
      Conn: sqlDB,
    }), &gorm.Config{})
    

GORM约定大于配置

  1. GORM 使用 ID 作为主键

  2. 使用结构体名的 蛇形复数 作为表名

  3. 字段名的 蛇形 作为列名(蛇形命名法:各个单词之间通过下划线“_”连接)

  4. 使用 CreatedAtUpdatedAt 字段追踪创建、更新时间

  5. 修改约定的CreatedAtUpdatedAt 字段填充数值类型,默认是time,可以修改成填充时间戳数

    type User struct {
      CreatedAt time.Time // 在创建时,如果该字段值为零值,则使用当前时间填充
      UpdatedAt int       // 在创建时该字段值为零值或者在更新时,使用当前时间戳秒数填充
      Updated   int64 `gorm:"autoUpdateTime:nano"` // 使用时间戳填纳秒数充更新时间
      Updated   int64 `gorm:"autoUpdateTime:milli"` // 使用时间戳毫秒数填充更新时间
      Created   int64 `gorm:"autoCreateTime"`      // 使用时间戳秒数填充创建时间
    }
    
  6. GORM 支持以下 tag语法: tag 名大小写不敏感,推荐使用小驼峰命名法

数据库CURD操作

创建

​ gorm支持结构体变量创建单一记录、切片批量创建记录、根据Map创建记录,指定字段创建记录

// 1.单一创建记录
user := User{Name: "Song", Age: 18, Birthday: time.Now()}
result := db.Create(&user) // 通过数据的指针来创建
user.ID             // 返回插入数据的主键
result.Error        // 返回 error
result.RowsAffected // 返回插入记录的条数
// 2.批量创建
var users = []User{{Name: "song11"}, {Name: "song22"}, {Name: "song33"}}
db.Create(&users)
// 创建后,回填主键的值
for _, user := range users {
  user.ID // 1,2,3
}
// 3. 根据Map创建, 主键也不会回填
db.Model(&User{}).Create(map[string]interface{}{
  "Name": "jinzhu", "Age": 18,
})
// batch insert from `[]map[string]interface{}{}`
db.Model(&User{}).Create([]map[string]interface{}{
  {"Name": "jinzhu_1", "Age": 18},
  {"Name": "jinzhu_2", "Age": 20},
})
// 3.指定字段创建
db.Select("Name", "Age", "CreatedAt").Create(&user)
// INSERT INTO `users` (`name`,`age`,`created_at`) VALUES ("name", 18, "2023-02-04 11:02:22.725")
db.Omit("Name", "Age", "CreatedAt").Create(&user)
// INSERT INTO `users` (`birthday`,`updated_at`) VALUES ("2023-01-01 00:00:00.000", "2023-02-04 11:05:21.775")

查询

  1. 查询单个记录:GORM 提供了 FirstLast 方法,没有找到记录时,它会返回 ErrRecordNotFound 错误

    // 获取第一条记录(主键升序)
    db.First(&user)
    // SELECT * FROM users ORDER BY id LIMIT 1;
    
    // 获取最后一条记录(主键降序)
    db.Last(&user)
    // SELECT * FROM users ORDER BY id DESC LIMIT 1;
    
    result.RowsAffected // 返回找到的记录数
    result.Error        // returns error
    
    // 检查 ErrRecordNotFound 错误
    errors.Is(result.Error, gorm.ErrRecordNotFound)
    
  2. 查询全部对象

    // 获取全部记录
    result := db.Find(&users)
    // SELECT * FROM users;
    
    result.RowsAffected // 返回找到的记录数,相当于 `len(users)`
    result.Error        // returns error
    
  3. 查询条件支持String,Struct,Map

更新

  1. Save 会保存所有的字段,即使字段是零值
  2. 使用 Update 更新单个列时,你需要指定条件,当使用了 Model 方法,且该对象主键有值,该值会被用于构建条件
  3. 更新多列,Updates 方法支持 structmap[string]interface{} 参数

删除

  1. 删除一条记录时,使用db.Delete删除对象需要指定主键,否则会触发批量删除

  2. 批量删除

    db.Delete(&users, []int{1,2,3})
    // DELETE FROM users WHERE id IN (1,2,3);
    
  3. 软删除

    • 如果数据库表包含了一个 gorm.deletedat 字段,则自动获得软删除的能力

    • 软删除能力的模型调用 Delete 时,记录不会被从数据库中真正删除,GORM 会将 DeletedAt 置为当前时间标记已经删除的意思,默认为0

    • 查看软删除记录

      db.Unscoped().Where("age = 20").Find(&users)
      // SELECT * FROM users WHERE age = 20;
      

事务

  1. Gorm 提供了 Begin、Commit、Rollback 方法用于使用事务
  2. Gorm 提供了 Tansaction 方法用于自动提交事务,避免用户漏写 Commit、 Rollbcak。

Hook

  1. GORM 在 提供了 CURD 的 Hook 能力
  2. Hook 是在创建、查询、更新、删除等操作之前、之后自动调用的函数
  3. 如果任何 Hook 返回错误,GORM 将停止后续的操作并回滚事务

参考资料

《GORM 中文文档》 | Go 技术论坛 (learnku.com)

编程时常用命名规则(驼峰命名法、蛇形命名法、串式命名法)_Al资料站与复盘笔记的博客-CSDN博客_蛇形命名法

GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.

‌⁡⁤⁢⁣⁡⁢⁢⁣⁡⁡‍⁣⁢⁣⁣‬‬‌⁢⁤⁢⁣⁣⁣‌‬‬‍⁡‌‍‍‬Go 框架三件套详解.pptx - 飞书云文档 (feishu.cn)