单表模型与单表操作
937字约3分钟
2025-02-15
表结构
在gorm中,使用结构体表示一张表,通常情况下,我们会使用Model结尾表示它是表的结构体
type UserModel struct {
ID int64 `gorm:"primaryKey"` // 主键
Name string `gorm:"not null;unique"` // 不能为空,且唯一
CreatedAt time.Time // 在创建记录时自动设置为当前时间
}
标签参考: gorm标签
自动生成表
package main
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"time"
)
type UserModel struct {
ID int64 `gorm:"primaryKey"` // 主键
Name string `gorm:"not null;unique"` // 不能为空,且唯一
CreatedAt time.Time // 在创建记录时自动设置为当前时间。
}
func main() {
// 连接数据库
db, err := gorm.Open(mysql.Open("root:root@tcp(127.0.0.1:3306)/gorm_new_db?charset=utf8mb4&parseTime=True&loc=Local"), &gorm.Config{})
if err != nil {
fmt.Println(err)
return
}
err = db.AutoMigrate(&UserModel{})
if err != nil {
fmt.Println(err)
return
}
fmt.Println("生成表结构成功!")
}
单表操作
插入数据
// InsertData 插入数据
func InsertData() {
user := UserModel{Name: "张三"}
err := DB.Create(&user).Error
// 创建成功之后,数据会回填
fmt.Println(user, err)
}
批量插入
// InsertData 插入数据
func InsertData() {
var users = []UserModel{
{
Name: "王五",
},
{
Name: "李四",
},
}
err := DB.Create(&users).Error
fmt.Println(users, err)
}
注意
Create函数接收的参数是结构体的指针或者是切片
插入数据的钩子
type UserModel struct {
ID int64 `gorm:"primaryKey"` // 主键
Name string `gorm:"not null;unique"` // 不能为空,且唯一
CreatedAt time.Time // 在创建记录时自动设置为当前时间。
}
func (u *UserModel) BeforeCreate(tx *gorm.DB) error {
fmt.Println("创建的钩子函数")
u.Name = "阿哲"
return nil
}
如果在插入的钩子函数中,返回错误,则数据不会被插入
查询数据
// 查全部
var users []UserModel
DB.Find(&users)
fmt.Println(users)
// 带条件查询
users = []UserModel{}
DB.Find(&users, "name = ?", "张三")
fmt.Println(users)
// 获取一条记录
var user UserModel
DB.Take(&user)
fmt.Println(user)
// 如果查不到则会报错
user = UserModel{}
err := DB.Take(&user, "id = ?", 100).Error
if err == gorm.ErrRecordNotFound {
fmt.Println("不存在的记录")
}
// 如果不想出现错误
user = UserModel{}
err = DB.Limit(1).Find(&user, "id = ?", 100).Error
fmt.Println(err)
// 打印实际的sql
DB.Debug().Take(&user, "id = ?", 1)
更新
有很多方法,Save、Update、UpdateColumn、Updates
不同的方法有不同的区别,如下:
- Save,有主键记录就是更新,并且可以更新零值,否则就是创建
- Update,可以更新零值,必须要有条件
- UpdateColumn,可以更新零值,不会走更新的Hook
- Updates,如果是结构体,则更新非零值,map可以更新零值
save
// 创建
var user = UserModel{
Name: "阿哲1",
}
DB.Save(&user)
fmt.Println(user)
// 更新
user = UserModel{
ID: 9,
Name: "阿哲2",
CreatedAt: time.Now(),
}
DB.Save(&user)
fmt.Println(user)
更新钩子
func (u *UserModel) BeforeUpdate(tx *gorm.DB) (err error) {
fmt.Println("更新的钩子函数")
return nil
}
Update和UpdateColumn
DB.Model(&UserModel{}).
Where("id = ?", 1).
Update("name", "张三") // 走了更新钩子
DB.Model(&UserModel{}).
Where("id = ?", 1).
UpdateColumn("name", "张三")
Updates
var user = UserModel{ID: 1}
DB.Model(&user).Updates(UserModel{
Name: "张三丰",
})
user = UserModel{ID: 2}
// 不会更新零值
DB.Model(&user).Updates(UserModel{
Name: "",
})
user = UserModel{ID: 2}
// 会更新零值
DB.Model(&user).Updates(map[string]any{
"name": "",
})
Expr 通常用于获取原字段的数据,例如年龄加一
DB.Model(&UserModel{}).
Where("id = ?", 1).
UpdateColumn("age", gorm.Expr("age + 1"))
删除
var user = UserModel{ID: 10}
DB.Delete(&user)
DB.Delete(&UserModel{}, 9)
// 批量删除
DB.Delete(&UserModel{}, []int{1, 2, 3})
钩子函数
func (u *UserModel) BeforeDelete(tx *gorm.DB) (err error) {
fmt.Println("删除钩子")
return
}
软删除
如果你的模型包含了 gorm.DeletedAt字段(该字段也被包含在gorm.Model中),那么该模型将会自动获得软删除的能力。
当调用Delete时,GORM并不会从数据库中删除该记录,而是将该记录的DeleteAt设置为当前时间,而后的一般查询方法将无法查找到此条记录。
查找被删除的记录
DB.Unscoped().Find(&users)
永久删除
DB.Unscoped().Delete(&user)