GORM介绍 | 豆包MarsCode AI刷题

101 阅读4分钟

GORM简介

GORM是什么?

GORM 是一个用于 Go 语言的对象关系映射(ORM)库,旨在简化数据库操作,提高开发效率。它支持多种关系型数据库,包括 MySQL、PostgreSQL、SQLite 和 SQL Server。

为什么要使用GORM?

相比于直接编写SQL语句,GORM提供了对 SQL 的封装,通过面向对象的方式操作数据库。开发者以模型(即struct)为中心,专注于数据逻辑,少量编码即可完成 CRUD 操作。

此外,GORM提供了内置功能,如自动迁移、关联管理、批量操作等,大大减少手动编写和调试 SQL 的工作量。

并且,GORM上手比直接写SQL语句简单很多(相信我)

GORM操作

GORM插入数据

GORM 使用 Go 的 struct 来定义数据库表的模型。

type User struct {
    ID       uint
    Name     string `gorm:"default:'unknown'"`
    Age      int
}

user := User{Name: "Alice", Age: 25}
db.Create(&user)
users := []User{
    {Name: "Bob", Age: 30},
    {Name: "Charlie", Age: 35},
}
db.Create(&users)

如上,使用 Create方法可以插入一条记录。插入记录后,userID 字段会被自动填充为插入记录的主键值。Create 方法接受一个指针类型的参数。想要插入多条记录,传递一个切片即可。

缺失的值会使用默认值。

或者,使用map来插入值。

db.Model(&User{}).Create(map[string]interface{}{ 
    "Name": "Eve", 
    "Age": 28,
    })

GORM错误处理

在 GORM 中,所有的数据库操作方法都会返回一个 *gorm.DB 类型的实例,提供对操作结果和错误的访问。

result := db.Create(&user)

GORM查询

First 方法

  • 用于查询第一条记录,按主键排序。
  • 如果没有找到匹配的记录,会返回 ErrRecordNotFound

Find 方法

  • 用于查询多条记录,结果是一个切片。
  • 如果没有找到任何记录,返回的切片是空的,但不会返回错误。

此外,GORM 支持通过结构体字段来构造查询条件。在结构体查询中,零值字段会被忽略,除非明确指定。GORM 默认会跳过未设置值的字段。解决办法可以使用指针,或map。

db.Where(&User{Age: new(int)}).Find(&users)
db.Where(map[string]interface{}{"Age": 0}).Find(&users)

GORM删除

GORM 使用 gorm.DeletedAt 来实现软删除。模型中包含这个字段后,调用 Delete 方法时会更新 deleted_at 字段为当前时间,而不是物理删除记录。

恢复记录

db.Model(&user).Update("deleted_at", nil)
db.Model(&User{}).Where("name = ?", "Alice").Update("deleted_at", nil)

事务

在数据库操作中,事务是一个逻辑操作单元,包含一组要么全都成功、要么全都失败的操作。事务具有以下特性:

原子性:事务中的操作要么全部成功,要么全部失败。

一致性:事务执行前后,数据库状态保持一致。

隔离性:并发事务互不干扰。

持久性:一旦事务提交,其结果永久保存到数据库。

典型场景是银行转账:一个账户扣款,另一个账户加款,这两个操作必须同时成功或同时失败。

GORM事务

Begin启动一个事务,返回一个新的 *gorm.DB 对象。该对象在事务完成前,执行的所有操作都在事务中。

Commit提交事务,保存所有事务中的更改。只有在所有操作成功时才调用 Commit

Rollback回滚事务,撤销事务中的所有更改。如果事务中任何一步失败,调用 Rollback

func PerformTransaction(db *gorm.DB) {
    tx := db.Begin() 
    if tx.Error != nil { 
        fmt.Println("Failed to begin transaction:", tx.Error) 
        return 
     }
     if err := tx.Create(&User{Name: "Alice"}).Error; err != nil {
         tx.Rollback()
         fmt.Println("Transaction failed:", err) 
         return 
     } 
     if err := tx.Create(&User{Name: "Bob"}).Error; err != nil {
         tx.Rollback()  
         fmt.Println("Transaction failed:", err) 
         return 
     }  
     if err := tx.Commit().Error; err != nil { 
         fmt.Println("Failed to commit transaction:", err) 
     }
     else { 
         fmt.Println("Transaction committed successfully") 
     } 
}

简化事务:Transaction方法

db.Transaction(func(tx *gorm.DB) error {
    if err := tx.Create(&User{Name: "Alice"}).Error; err != nil {
        return err
    }

    if err := tx.Create(&User{Name: "Bob"}).Error; err != nil {
        return err
    }

    return nil
})

特点:如果 Transaction 函数返回 error,事务会自动回滚。如果返回 nil自动提交。

钩子

在 GORM 中,钩子(Hook)是指在特定的数据库操作(如创建、更新、删除等)执行之前或之后自动触发的函数。钩子为开发者提供了一种在数据持久化过程中添加自定义逻辑的方法。

如果钩子返回 error,当前操作会被中止,返回该错误。并且钩子方法在事务中执行,未提交时数据不会持久化。