GORM 学习笔记 02-单表模型和单表操作

AI-摘要
Yuan GPT
AI初始化中...
介绍自己 🙈
生成本文简介 👋
推荐相关文章 📖
前往主页 🏠
前往爱发电购买
GORM 学习笔记 02-单表模型和单表操作
SEAlencehegorm的引入肯定是为了我们更好的操作数据库
在使用原生sql查询的时候
最大的问题就是没办法映射到结构体上
我们不难发现,数据库里面的记录就很想一个结构体,数据库的一列对应一个字段
所以数据库到结构体的映射就是orm的一个最大特点
所有的orm都是如此
使用一个类或者一个结构体表示一张表
然后使用一个实例化对象表示一条记录
字段表示列
安装
go get -u gorm.io/gorm
go get gorm.io/driver/mysql
一个简单的示例
package main
import (
//"database/sql"
//"fmt"
//"log"
"fmt"
//引入驱动
_ "github.com/go-sql-driver/mysql"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
// 用结构体来表示一个表
type User struct {
ID int
Username string
Age int
}
// 在结构体中指定表名
func (User) TableName() string {
return "user"
}
func main() {
//连接数据库
//数据源名称(用户名:密码@tcp(地址)/库名)
dsn := "root:888888@tcp(127.0.0.1:3306)/mydb"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println(err)
return
}
//fmt.Println(db)
//查询
//实例化切片
var userList []User
db.Find(&userList)
fmt.Println(userList)
}
[{1 wangwu 19} {2 lisi 20} {3 zhangsan 18} {4 fengfeng 23} {5 fangfang 18} {6 fengfengzhidao 25} {7 feifei12138 28} {8 lier 29}]
单表模型
用一个 Go 结构体(struct)来对应数据库中的一张表。结构体的字段对应表的列
表结构
在gorm中,使用结构体表示一张表
例如User表
通常情况下,我们会使用Model结尾表示它是表的结构体
type UserModel struct {
ID int64 `gorm:"primaryKey"` // 主键
Name string `gorm:"not null;unique"` // 不能为空,且唯一
CreatedAt time.Time // 在创建记录时自动设置为当前时间
}
标签参考这个 https://gorm.io/zh_CN/docs/models.html#字段标签
为了方便可以建一个全局变量
package global
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var DB *gorm.DB
func Connect() {
dsn := "root:888888@tcp(127.0.0.1:3306)/mydb"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println(err)
return
}
DB=db
}
自动生成表
让 GORM 根据结构体的定义,自动在数据库里创建或更新表结构
生成表结构只会新增字段,不会删除字段和更新字段
package main
import (
"fmt"
"gorm_study/global"
"time"
)
type UserModel struct {
ID int //一般不写就是默认主键
Usernamme string `gorm:"not null;unique"`
Age int `gorm:"default:18"`
CreatedAt time.Time
}
func migrate() {
fmt.Println(global.DB)
//表迁移
err := global.DB.AutoMigrate(&UserModel{})
if err != nil {
fmt.Println("表结构迁移失败:", err)
return
}
fmt.Println("表结构迁移成功")
}
func main() {
global.Connect()
migrate()
}
单表操作
插入数据
为了方便可以单独创建 models 下一个 user_model
package models
import "time"
type UserModel struct {
ID int //一般不写就是默认主键
Usernamme string `gorm:"not null;unique"`
Age int `gorm:"default:18"`
CreatedAt time.Time
}
package main
import (
"fmt"
"gorm_study/global"
"gorm_study/models"
)
func main() {
global.Connect()
//插入数据(一次插入)
err := global.DB.Create(&models.UserModel{
Usernamme: "张三",
Age: 25,
}).Error
if err != nil {
fmt.Println(err)
}
}
回填式创建
//回填式插入
user := models.UserModel{
Usernamme: "lisi",
Age: 25,
}
err := global.DB.Create(&user).Error
if err != nil {
fmt.Println(err)
}
fmt.Println(user.ID, user.CreatedAt, user.Usernamme)
添加多个
var userList = []models.UserModel{
{Usernamme: "李四"},
{Usernamme: "wangwu"},
}
err := global.DB.Create(&userList).Error
if err != nil {
fmt.Println(err)
}
特别注意:Create函数接收的参数是结构体的指针或者是切片
插入数据的钩子
package models
import (
"errors"
"fmt"
"time"
"gorm.io/gorm"
)
type UserModel struct {
ID int //一般不写就是默认主键
Usernamme string `gorm:"not null;unique"`
Age int `gorm:"default:18"`
CreatedAt time.Time
}
// 钩子函数
func (u *UserModel) BeforeCreate(*gorm.DB) error {
fmt.Println("创建钩子")
return errors.New("xxxx")
}
查询数据
func query() {
var userList []models.UserModel
//查全部
global.DB.Find(&userList)
fmt.Println(userList)
}
注意此时会报错,连接数据库需要加参数
dsn := "root:888888@tcp(127.0.0.1:3306)/mydb?parseTime=true&loc=Local"
// 查全部
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
func updateSave() {
var user models.UserModel
//user.ID = 3
user.CreatedAt = time.Now()
user.Usernamme = "miaomiao2"
global.DB.Save(&user)
fmt.Println(user)
}
update
func update() {
var user = models.UserModel{ID: 1}
global.DB.Model(&user).Update("usernamme", "zhangsan")
fmt.Println(user)
}
更新的钩子
func (u *UserModel) BeforeUpdate(tx *gorm.DB) (err error) {
fmt.Println("更新的钩子函数")
return nil
}
Updates
func updates() {
var user = models.UserModel{ID: 1}
//global.DB.Model(&user).Updates(models.UserModel{
// Usernamme: "张三",
// Age: 18,
//})
global.DB.Model(&user).Updates(map[string]any{
"Usernamme": "张三",
"Age": 0,
})
fmt.Println(user)
}
Expr
通常用于获取原字段的数据
例如年龄加一
global.DB.Model(&user).Update("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设置为当前时间,而后的一般查询方法将无法查找到此条记录。
type UserModel struct {
ID int //一般不写就是默认主键
Usernamme string `gorm:"not null;unique"`
Age int `gorm:"default:18"`
CreatedAt time.Time
DeletedAt gorm.DeletedAt
}
新增加了列要迁移
func Migrate() {
err := DB.AutoMigrate(&models.UserModel{})
if err != nil {
log.Fatalf("数据库迁移失败: %s", err)
}
fmt.Println("数据库迁移成功")
}
查找被删除的记录
var user models.UserModel
global.DB.Unscoped().Take(&user, 3)
fmt.Println(user)
永久删除
global.DB.Unscoped().Delete(&user)
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果

