这是我参与「第五届青训营 」伴学笔记创作活动的第 7 天
内容源于青训营课堂视频以及一些go文档和自己的经验、理解,若有错误欢迎及时指出
三件套介绍(Gorm/Kitex/Hertz)
- Gorm:一个迭代了十多年的功能强大的ORM框架
- Kitex:字节内部的golang微服务RPC框架,高性能、高扩展特点,支持多协议并且有丰富的开源扩展
- Hertz:字节内部的HTTP框架,最初是在gin基础上再开发的
Gorm的基础使用
模型定义
Models are normal structs with basic Go types, pointers/alias of them or custom types implementing Scanner and Valuer interfaces
GORM倾向于约定而不是配置,默认以ID作为主键,结构体名的蛇形复数作为表名,字段名的蛇形作为列名,使用CreatedAt、UpdatedAt字段作为创建、更新时间。
type User struct {
ID uint
Name string
Email *string
Age uint8
Birthday *time.Time
MemberNumber sql.NullString
ActivedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
}
gorm.Model
自定义配置
// gorm.Model 的定义
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
更多的高级选项可参考模型定义高级选项
连接数据库
目前官方支持的有MySQL, PostgreSQL, SQlite, SQL Server
dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
CRUD接口
-
创建
user := User{Name: "Ltd", Age: 12, Birthday: time.Now()} result := db.Create(&user) // 通过数据的指针来创建 user.ID // 返回插入数据的主键 result.Error // 返回 error result.RowsAffected // 返回插入记录的条数 -
查询
GORM 提供了
First、Take、Last方法,以便从数据库中检索单个对象。当查询数据库时它添加了LIMIT 1条件,且没有找到记录时,它会返回ErrRecordNotFound错误// 获取第一条记录(主键升序) db.First(&user) // SELECT * FROM users ORDER BY id LIMIT 1; // 获取一条记录,没有指定排序字段 db.Take(&user) // SELECT * FROM users LIMIT 1; // 获取最后一条记录(主键降序) db.Last(&user) // SELECT * FROM users ORDER BY id DESC LIMIT 1; result := db.First(&user) result.RowsAffected // 返回找到的记录数 result.Error // returns error // 检查 ErrRecordNotFound 错误 errors.Is(result.Error, gorm.ErrRecordNotFound)使用结构体作为查询条件时,GORM只会查询非零字段,这意味着若字段为对应类型的零值。那么不会作为查询条件,而需要使用Map来构建查询条件
db.WHere(&User{Name: "Ltd", Age: 0}).Find(&user) // SELECT * FROM users WHERE name = "Ltd" db.WHere(map[string]interface{}{Name: "Ltd", Age: 0}).Find(&user) // SELECT * FROM users WHERE name = "Ltd" AND age = 0 -
更新
Updates方法支持struct和map[string]interface{}参数。当使用struct更新时,默认情况下,GORM 只会更新非零值的字段// 根据 `struct` 更新属性,只会更新非零值的字段 db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false}) // UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111; // 根据 `map` 更新属性 db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false}) // UPDATE users SET name='hello', age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;如需更新零值可以使用Map或Select选择字段
-
删除
删除一条记录时,删除对象需要指定主键,否则会触发批量Delete,例如:
db.Delete(&User{}, 10)
// DELETE FROM users WHERE id = 10;
db.Delete(&User{}, "10")
// DELETE FROM users WHERE id = 10;
db.Delete(&users, []int{1,2,3})
// DELETE FROM users WHERE id IN (1,2,3);
db.Where("name LIKE ?", "%Ltd%").Delete(User{})
// DELETE from users where name LIKE "%Ltd%";
如果您的模型包含了一个 gorm.deletedat 字段(gorm.Model 已经包含了该字段),它将自动获得软删除的能力!
拥有软删除能力的模型调用 Delete 时,记录不会被从数据库中真正删除。但 GORM 会将 DeletedAt 置为当前时间, 并且你不能再通过正常的查询方法找到该记录。
使用 Unscoped 找到被软删除的记录
db.Unscoped().Where("age = 20").Find(&users)
// SELECT * FROM users WHERE age = 20;
永久删除
db.Unscoped().Delete(&order)// DELETE FROM orders WHERE id=10;