课程笔记 - Web开发三件套 - GROM | 青训营笔记

75 阅读3分钟

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


GORM

gorm 是字节团队研发的一款面向 golang 的 orm 框架,详见:gorm.io/zh_CN/

DSN

DSN是数据源名称Data Source Name,是应用程序用来请求与ODBC数据源连接的名称。连接到ODBC时,它会存储连接详细信息,例如数据库名称、目录、数据库驱动程序、UserID、password等。

约定

在项目开发中,我们常常秉持着约定大于配置的设计理念,在 gorm 中也有类似的设计,具体表现为:

约定

  • 使用名为 ID 的字段作为主键 / gorm:"primaryKey"
  • 默认使用结构体名的 蛇形命名 作为表名 / 实现 Tabler 接口更改表名
  • ...

model

在 gorm 中,使用结构体进行数据模型的绑定:

// Product gorm model
type Product struct {
   ID        uint           `gorm:"primaryKey"`
   Code      string         `gorm:"column: code;"`
   Price     uint           `gorm:"column: user_id"`
   Age       int32          `gorm:"default:18"` // default
   DeletedAt gorm.DeletedAt // gorm 提供软删除实现
}

// TableName 约定,定义表名
func (Product) TableName() string {
   return "product"
}

优化

gorm 默认为每个 sql 操作都开启了事务,可以关闭这一配置来提升执行的性能。同时,gorm 也提供了缓存预编译语句的选项,结合使用场景可以适当打开此配置以复用语句,提高性能。

var config *gorm.Config = &gorm.Config{
	SkipDefaultTransaction: true, // 关闭默认 CRUD 事务
	PrepareStmt:            true, // 缓存预编译语句
}

基础操作

因文档介绍详细,在此仅列出部分常用操作,具体内容可自行查看文档。

  • connect
db, _ := gorm.Open(mysql.Open("dsn"))
db.Clauses(clause.OnConflict{DoNothing: true}) // Upsert
  • create
tx := db.Create(&Product{Code: "6", Price: 6})
if tx.Error != nil {
   fmt.Println(tx.Error)
}
  • read
var product Product
// 当使用结构体作为条件查询时,gorm 只查询非零字段(非0,false,""等)不会用于构建查询条件(Map除外)
var products = make([]*Product, 0)
// first 默认按主键升序排序
// 使用 first 时,若查询不到数据会返回 ErrRecordNotFound
// SELECT * FROM table ORDER BY id LIMIT 1
db.First(&product, 1) // 默认整型主键
db.First(&product, "code = ?", "6")
// 使用 find 查询不到数据时不报错
// SELECT * FROM table WHERE name LIKE ''
db.Where("name LIKE ?", "%n%").Find(&products)
// SELECT * FROM table WHERE name = '' AND age >= x
db.Where("code = ? AND age >= ?", "a", 18).Find(&products)
  • update
// 使用 Model || Table 设置表名
db.Model(&product).Where("age > ?", 18).Update("Price", 200)
// 使用 struct 更新属性时,只会更新非零值字段(用Map或Select指定字段可以更新)
db.Model(&Product{Id: 1}).Updates(Product{Price: 666})
// 更新选定字段:UPDATE table SET name=x WHERE id=x
db.Model(&Product{Id: 1}).Select("name").Updates(map[string]interface{}{
   "name": "hello", "age": 18,
})
  • delete
// 拥有软删除能力的 Model 调用 Delete 时,记录不会被真正删除,gorm会将 DeletedAt 置为当前时间,并不再能通过正常的查询方式找到
// 使用 Unscoped 可以查询到被软删除的数据
db.Delete(&product, 1) // 默认整型主键
  • transaction
// db#Begin 固化事务连接,返回已开启事务的单独连接对象(从池中摘除
tx = db.Begin()
if err := tx.Create(&Product{Code: "aaa"}).Error; err != nil {
        tx.Rollback()
        return
}
tx.Commit()
// gorm 提供了 Transaction 方法用于自动提交事务,避免漏写 Commit Rollback
if err := db.Transaction(func(tx *gorm.DB) error {
        if err := tx.Create(&Product{Code: "aaa"}).Error; err != nil {
                return err // auto rollback
        }1
        return nil // auto commit
}); err != nil {
        return
}