Gorm的基本使用 | 青训营笔记

116 阅读2分钟

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

课堂笔记

定义 gorm model

模型是标准的 struct,由 Go 的基本数据类型、实现了 Scanner 和 Valuer 接口的自定义类型及其指针或别名组成。

type User struct {
    ID           uint
    Name         string
    Email        *string
    Age          uint8
    Birthday     *time.Time
    MemberNumber sql.NullString
    ActivatedAt  sql.NullTime
    CreatedAt    time.Time
    UpdatedAt    time.Time
}

为 model 定义表名

func (p Product) TableName() string {
    return 'product'
}

链接MySQL数据库

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

gorm 的约定(默认)

  • gorm使用名为ID的字段作为主键
  • 使用结构体的蛇形负数作为表名
  • 字段名的蛇形作为列名
  • 使用CreatedAt、UpdatedAt字段作为创建、更新时间

gorm 支持的数据库

GORM 官方支持的数据库类型有: MySQL, PostgreSQL, SQlite, SQL Server

gorm.io/zh_CN/docs/…

GORM 通过驱动来连接数据库,如果需要连接其他类型的数据库,可以复用/自行开发驱动

DSN

github.com/go-sql-driv…

gorm 创建数据

通过使用gorm tag创建与字段名不同的列名

package main

import(
    "fmt"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)
type Product struct {
    ID    uint    `gorm:"primarykey"`
    Code  string  `gorm:"column: code"`
    Price uint    `gorm:"column: user_id"`
}

创建一条

p := Product{Code: "D42"}
res := db.Create(&p)    // 通过数据的指针来创建
fmt.Println(res.Error) // 获取 err
fmt.Println(p.ID)      // 返回插入数据的主键

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

创建多条

products := []*Product{{Code: "D41"}, {Code: "D42"}, {Code: "D43"}}
res = db.Create(&products)
fmt.Println(res.Error) // 获取 err
for _, p := range products {
    fmt.Println(p.ID)
}

使用Upsert

使用 clause.OnConflict 处理数据冲突

// 以不处理冲突为例,创建一条数据
p := Product{Code: "D42", ID: 1}
db.Clauses(clause.OnConflict{DoNothing: true}).Create(&p)

使用默认值

通过使用 default 标签为字段定义默认值

type User struct {
    ID    int64
    Name  string `gorm:"default:galeone"`
    Age   int64  `gorm:"default:18"`
}

gorm 查询数据

检索单个对象

使用First时,需要注意查询不到数据会返回 ErrRecordNotFound。

使用 Find 查询多条数据,查询不到数据不会返回错误。

u := User{}
db.First(&u)

查询多条数据

users := make([]*User, 0)
// SELECT * FROM users where age > 10;
result := db.Where("age > 10").Find(&users)
fmt.Println(result.RowsAffected)  // 返回找到的记录数,相当于'len(users)'
fmt.Println(result.Error)         // returns error
// IN SELECT * FROM users WHERE name IN('jinzhu', 'jinzhu 2');
db.Where("name IN ?", []string{"jinzhu", "jinzhu 2"})
// LIKE SELECT * FROM users WHERE name LIKE '%jin%';
db.Where("name LIKE ?", "%jin%").Find(&users)
// AND SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;
db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users)

使用结构体作为查询条件

当使用结构体作为条件查询时,GORM只会查询非零值字段。这意味着如果您的字段值为0、false或其他零值,该字段不会用于构建查询条件,使用Map来构建查询条件。

// SELECT * FROM users WHERE name = "jinzhu";
db.Where(&User{Name: "jinzhu", Age: 0}).Find(&users)
// SELECT * FROM users WHERE name = "jinzhu" AND age = 0;
db.Where(map[string]interface{}{"Name": "jinzhu", "Age": 0}).Find(&users)