GORM的基本使用
Gorm model
定义一个映射数据库表的结构体,这类结构体称为model
type Orders struct {
Id uint `gorm:"primary_key" json:"id"`
GameId uint `json:"gameId"`
ChannelId uint `json:"channel_id"`
CreatedBy string `json:"createdBy"`
CreatedAt time.Time `json:"createdAt"`
UpdateBy string `json:"updateBy"`
UpdateAt time.Time `json:"updateAt"`
}
func (o Orders) TableName() string {
return "Orders"
}
数据库连接
首先,分别安装 gorm 库本身以及 MySQL 数据库驱动
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
"github.com/jinzhu/gorm"也是一个受欢迎的开源的gorm库
与gorm.io/gorm的使用大同小异
在代码中导入相关的包
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
进行数据库连接初始化,通过dsn字符串配置所需连接的数据库
调用 gorm.Open 方法完成数据库连接对象 db 的初始化
如果出现连接错误,则通过 panic 抛出异常信息
func main() {
dsn := "root:12345678@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("db connect fail")
}
}
数据库CRUD操作
创建操作(Create)
通过db.Create()进行插入数据,参数为一个model对象
批量插入则传入一个model对象的slice
//插入
db.Create(&Orders{
GameId: 1,
ChannelId: 1,
})
//批量插入
ordersArr := []Orders{
{GameId: 2, ChannelId: 2},
{GameId: 3, ChannelId: 3},
{GameId: 4, ChannelId: 4},
}
db.Create(&ordersArr)
查询操作(Read)
查询单条数据
通过db.First查询单条数据,第一个参数为查询对应的model对象
后续参数为查询条件
var orders Orders
db.First(&orders, 1) // 查找主键id为1的数据
db.First(&orders, "gameId = ?", 1) // 查找gameId为1的数据
db.First(&orders, "channel_id = ?", 1) // 查找channel_id为1的数据
多条件查询
还可以通过db.Find查询数据,查询条件可以作为后续参数传入,或是通过db.Where指明查询条件
db.Order用来指明排序条件
var ordersResult []Orders
db.Find(&ordersResult, "gameId < ? AND channel_id < ?", 10, 10)
db.Where("gameId < ? AND channel_id < ?", 10, 10).Find(&ordersResult)
db.Where("gameId < ? AND channel_id < ?", 10, 10).Find(&ordersResult).Order("gameId Desc")
分页查询
var ordersResult []Orders
page := 2
pageSize := 10
offset := (page - 1) * pageSize
db.Offset(offset).Limit(pageSize).Find(&ordersResult)
更新操作(Update)
db.Model 用于指定所针对的model(也就是对应数据库中的表)
通过db.Model和db.Updates配合使用完成更新,可以根据model对象和map进行更新
当使用map进行更新时,我们可以更新零值
更新条件由db.Model中传递的对象中的值指定,或是通过db.Where指明更新条件(优先)
//UPDATE orders SET game_id = 10,channel_id = 10 WHERE id = 1;
db.Model(&Orders{Id: 1}).Updates(Orders{GameId: 10, ChannelId: 10})
//UPDATE orders SET game_id = 10,channel_id = 10 WHERE id = 1;
db.Model(&Orders{Id: 1}).Updates(map[string]interface{}{"gameId": 10, "channel_id": 10})
//UPDATE orders SET game_id = 20,channel_id = 20 WHERE id = 2;
db.Model(&Orders{Id: 1}).Updates(map[string]interface{}{"gameId": 20, "channel_id": 20}).Where(" id = ?", 2)
删除操作(Delete)
删除单个记录
通过db.Delete删除对应的数据
db.Delete(&Orders{Id: 1})
条件和批量删除
通过db.where进行条件批量地删除
db.Delete(&Orders{}).Where("gameId < ? " ,10)
软删除
软删除是说我们的数据不是真正从数据库中删除记录,而是标记记录已删除
type Orders struct {
Id uint `gorm:"primary_key" json:"id"`
GameId uint `json:"gameId"`
ChannelId uint `json:"channel_id"`
CreatedBy string `json:"createdBy"`
CreatedAt time.Time `json:"createdAt"`
UpdateBy string `json:"updateBy"`
UpdateAt time.Time `json:"updateAt"`
DeletedAt gorm.DeletedAt
}
通过添加 DeletedAt 字段实现,添加后与正常的删除操作一致,但是实现的是软删除
软删除后,记录仍然在数据库中,但通过常规查询不会被查到,除非使用db.Unscoped查询
var orders Orders
db.Unscoped().First(&orders, 1)
Gorm Hook
回调函数
是在CRUD前后自动调用的函数
一般使用场景:
CRUD前设置CreatedBy、CreatedAt、UpdateBy、UpdateAt字段的自动填充,减少代码工作量
CRUD后更新关联表的操作(更推荐在业务代码中实现)
type Orders struct {
Id uint `gorm:"primary_key" json:"id"`
GameId uint `json:"gameId"`
ChannelId uint `json:"channel_id"`
CreatedBy string `json:"createdBy"`
CreatedAt time.Time `json:"createdAt"`
UpdateBy string `json:"updateBy"`
UpdateAt time.Time `json:"updateAt"`
Deleted gorm.DeletedAt
}
func (receiver Orders) TableName() string {
return "Orders"
}
func (o *Orders) BeforeCreate(tx *gorm.DB) error {
// 实际中从请求上下文获取
o.CreatedBy = "system"
o.CreatedAt = time.Now()
return nil
}
func (o *Orders) BeforeUpdate(tx *gorm.DB) error {
o.UpdateBy = "system"
o.UpdateAt = time.Now()
return nil
}
// AfterCreate回调函数,用于在创建记录后输出表名和执行的SQL语句
func (o *Orders) AfterCreate(tx *gorm.DB) error {
tableName := o.TableName()
sql := tx.Dialector.Explain(tx.Statement.SQL.String(), tx.Statement.Vars...)
log.Printf("数据库表名: %s, 完整sql: %s", tableName, sql)
return nil
}