文章目录
- 一、什么是GORM?
- 二、GORM连接mysql以及AutoMigrate创建表
- 三、查询
- 1、检索此对象是否存在于数据库(First,Take,Last方法)
- 2、Find()方法检索
- 3、根据指定字段查询
- 四、更新
- 1、Save() 保存多个字段
- 2、更新单个字段
- 五、删除
一、什么是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)