这是我参与「第五届青训营」伴学笔记创作活动的第 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 通过驱动来连接数据库,如果需要连接其他类型的数据库,可以复用/自行开发驱动
DSN
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)