GORM的常见命令

发布于:2024-05-08 ⋅ 阅读:(29) ⋅ 点赞:(0)

一、什么是GORM?

GORM 是 Go 语言中一个非常流行的 ORM(对象关系映射)库,它提供了一种简单而强大的方式来将 Go 结构体映射到数据库表,并提供了丰富的方法来操作数据库,比如查询、插入、更新和删除数据等。

二、GORM连接mysql以及AutoMigrate创建表

使用GORM之前先获取包:

go get "gorm.io/driver/mysql"
go get "gorm.io/gorm"

数据库的连接:

	db, _ = gorm.Open(mysql.New(mysql.Config{
		DSN: "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local",
	}), &gorm.Config{
		SkipDefaultTransaction:                   true, // 禁用默认事务(提高运行速度)
		DisableForeignKeyConstraintWhenMigrating: true, // 禁用外键约束
		NamingStrategy: schema.NamingStrategy{
			//TablePrefix:   "t_", // 表名前缀,`User` 的表名应该是 `t_users`
			SingularTable: true, // 使用单数表名,启用该选项
		},
	})

使用AutoMigrate自动创建表,在这里我们就要知道GORM里的模型是什么意思。
模型是使用普通结构体定义的。
也就是说,数据库中的表是根据我们自己建立的结构体生成的,我们可以在设计结构体的时候,在后边加上gorm的一些限制,然后自动迁移就可以在数据库中生成了。

gorm.Model

type Model struct {
	ID        uint `gorm:"primarykey"`
	CreatedAt time.Time
	UpdatedAt time.Time
	DeletedAt DeletedAt `gorm:"index"`
}

这是gorm已经定义好的结构体,可以直接使用。

案例1:创建一个用户表自动迁移到数据库中。

type User struct {
	gorm.Model
	Name string
	Age  int
}

func main() {
	db.AutoMigrate(&User{}) //自动迁移这个表
	user := User{
		Name: "张三",
		Age:  18,
	}
	rest := db.Create(&user)
	fmt.Println(user.ID) // 主键ID
	fmt.Println(rest.RowsAffected)
	fmt.Println(rest.Error)
}

案例2:自动创建一个嵌套的表组合。

type User struct {
	gorm.Model
	Name string
	Age  int
}

type Work struct {
	User
	Work string
}

func main() {
	err := db.AutoMigrate(&Work{}) //自动迁移这个表
	if err != nil {
		fmt.Println(err)
	}
	work := Work{User: User{Name: "张三", Age: 18}, Work: "程序员"}
	db.Create(&work)
	fmt.Println(work.ID)
}

三、查询

以下所有操作的基本数据库信息如下:
在这里插入图片描述

1、检索此对象是否存在于数据库(First,Take,Last方法)

GORM 提供了First、Take、Last方法,以便从数据库中检索单个对象。当查询数据库时它添加了 LIMIT 1 条件,且没有找到记录时,它会返回 ErrRecordNotFound 错误。

	//查询张三是否在数据库中
	//SELECT * FROM `work` WHERE name = '张2三' AND `work`.`deleted_at` IS NULL ORDER BY `work`.`id` LIMIT 1
	var work1 Work
	result := db.Where("name = ?", "张三").First(&work1)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			fmt.Println("没找到记录")
			return
		}
		fmt.Println(result.Error)
		return
	}
	fmt.Println(result.RowsAffected) // 受影响的行数

2、Find()方法检索

	// 查询age=20的所有的信息
	var works []Work
	result = db.Where("age = ?", 20).Limit(1).Find(&works)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			fmt.Println("没找到记录")
			return
		}
		fmt.Println(result.Error)
		return
	}
	fmt.Println(result.RowsAffected)
	for i, work := range works {
		fmt.Println(i, work)
	}

3、根据指定字段查询

	// 指定结构体查询字段
	var work2 []Work
	result11 := db.Select("name,age").Where("age = ?", 20).Limit(2).Find(&work2)
	if result.Error != nil {
		if errors.Is(result11.Error, gorm.ErrRecordNotFound) {
			fmt.Println("没找到记录")
			return
		}
		fmt.Println(result11.Error)
		return
	}
	fmt.Println(result11.RowsAffected)
	for i, work := range work2 {
		fmt.Println(i, work)
	}

四、更新

1、Save() 保存多个字段

Save 会保存所有的字段,即使字段是零值

保存 是一个组合函数。 如果保存值不包含主键,它将执行 Create,否则它将执行 Update (包含所有字段)。

	works := []Work{
		{User: User{Name: "张三", Age: 18}, Work: "程序员"},
		{User: User{Name: "李四", Age: 19}, Work: "程序员"},
		{User: User{Name: "王五", Age: 20}, Work: "程序员"},
	}
	result := db.Save(works)
	if result.Error != nil && result.RowsAffected == 0 {
		fmt.Println("保存失败")
		return
	}
	fmt.Println("保存成功")

2、更新单个字段

可以使用主键查询也可以是使用某个特定的字段查询,也可以同时使用查询。

	// 根据表的name进行修改信息
	result := db.Model(&Work{}).Where("name=?", "张三").Updates(map[string]interface{}{"age": 112, "work": "大佬"})
	if result.Error != nil {
		panic(result.Error)
	}
	if result.RowsAffected == 0 {
		panic("没有更新数据")
	}
	fmt.Println(result.RowsAffected)
	// 根据id修改信息
	var w Work
	w.ID = 1
	result = db.Model(&w).Updates(map[string]interface{}{"age": 32, "work": "行长"})
	if result.Error != nil {
		panic(result.Error)
	}
	if result.RowsAffected == 0 {
		panic("没有更新数据")
	}
	fmt.Println(result.RowsAffected)

五、删除

如果你的模型包含了 gorm.DeletedAt字段(该字段也被包含在gorm.Model中),那么该模型将会自动获得软删除的能力!

当调用Delete时,GORM并不会从数据库中删除该记录,而是将该记录的DeleteAt设置为当前时间,而后的一般查询方法将无法查找到此条记录。

软删除:

	// 根据主键删除
	var w Work
	w.ID = 7
	// db.Delete(&Work{}, 8) //一样的
	result := db.Where("age < ?", 98).Delete(&w)
	if result.Error != nil {
		panic(result.Error)
	}
	if result.RowsAffected == 0 {
		panic("没有删除任何数据")
	}
	fmt.Println(result.RowsAffected)

物理删除:

// 物理删除主键为 5 6的两条信息
db.Unscoped().Delete(&Work{}, 5, 6)