认识 GORM | 青训营笔记

77 阅读4分钟

认识 GORM

GORM 是一个基于Go语言的 ORM(对象关系映射)库,它的设计目标是提供简洁易用的 API ,同时又具备强大的功能和高效的性能。

基本用法

GORM 的基本用法非常简单,我们只需要定义一个结构体,然后通过 GORM 提供的 API 来进行增删改查等操作。例如,我们定义一个User结构体:

type User struct {
    ID       uint   `gorm:"primary_key"`
    Name     string `gorm:"not null;unique"`
    Age      int    `gorm:"not null"`
    Email    string `gorm:"not null;unique"`
    Password string `gorm:"not null"`
}

然后我们可以通过以下代码来进行增删改查等操作:

// 创建一个数据库连接
db, err := gorm.Open("mysql", "user:password@tcp(127.0.0.1:3306)/database?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil {
    panic(err)
}
defer db.Close()

// 自动迁移表结构
db.AutoMigrate(&User{})

// 创建记录
user := User{Name: "Tom", Age: 18, Email: "tom@example.com", Password: "password"}
db.Create(&user)

// 查询记录
var result User
db.Where("name = ?", "Tom").First(&result)

// 更新记录
db.Model(&result).Update("Age", 19)

// 删除记录
db.Delete(&result)

上述代码中,我们首先通过 gorm.Open()函数创建了一个数据库连接,并通过db.AutoMigrate()方法自动迁移表结构。然后我们创建了一个User记录,并通过db.Create()方法将其写入数据库。接着我们通过db.Where()方法查询了符合条件的记录,并通过db.First()方法将查询结果赋值给了result变量。最后,我们通过db.Model().Update()db.Delete()方法分别更新和删除了记录。

关键特性

除了基本用法之外,GORM 还提供了许多关键特性,下面我们将介绍其中的几个。

关联查询

GORM 支持多种类型的关联查询,包括一对一、一对多、多对多等。例如,我们可以定义一个Article结构体,并将其与User结构体进行关联:

type Article struct {
    ID      uint   `gorm:"primary_key"`
    Title   string `gorm:"not null"`
    Content string `gorm:"not null"`
    UserID  uint
    User    User `gorm:"foreignkey:UserID"`
}

然后我们可以通过以下代码进行关联查询:

// 查询用户的所有文章
var user User
db.Where("name = ?", "Tom").First(&user)
db.Model(&user).Related(&user.Articles)

// 查询文章的作者
var article Article
db.Where("title = ?", "Hello GORM").First(&article)
db.Model(&article).Association("User").Find(&article.User)

上述代码中,我们通过Article结构体中的UserID字段和User结构体进行了关联。然后我们可以通过db.Model().Related()方法查询用户的所有文章,并通过db.Model().Association().Find()方法查询文章的作者。

钩子函数

GORM 提供了多个钩子函数,用于在操作数据库之前或之后执行一些特定的逻辑。例如,我们可以在创建用户之前自动生成一个随机的加密密码:

func (user *User) BeforeCreate(tx *gorm.DB) error {
    password := generatePassword()
    user.Password = hashPassword(password)
    return nil
}

func generatePassword() string {
    // 生成随机密码
}

func hashPassword(password string) string {
    // 加密密码
}

db.Create(&user)

上述代码中,我们定义了一个BeforeCreate()钩子函数,在创建用户之前自动生成一个随机的加密密码,并将其赋值给user.Password字段。

事务

GORM 支持事务操作,可以确保在多个操作之间的数据一致性。例如,我们可以在一个事务中同时创建多个用户:

// 开启事务
tx := db.Begin()

// 创建用户
user1 := User{Name: "Alice", Age: 20, Email: "alice@example.com", Password: "password1"}
user2 := User{Name: "Bob", Age: 21, Email: "bob@example.com", Password: "password2"}
tx.Create(&user1)
tx.Create(&user2)

// 提交事务
tx.Commit()

上述代码中,我们通过db.Begin()方法开启了一个事务,并在事务中创建了两个用户。最后,我们通过tx.Commit()方法提交事务,确保所有的操作都执行成功。

思考和分析

GORM 作为一个 ORM 库,其主要的优点是简单易用、功能强大、性能高效。在实际项目中,我们可以通过GORM来快速地进行数据库操作,减少开发时间和代码量。同时,GORM 的关联查询、钩子函数和事务等特性也大大增强了其灵活性和可扩展性。

然而,在使用 GORM 的过程中,我们也需要注意一些细节。例如,GORM 的查询语句默认是单向的,无法通过关联查询来进行反向查询;同时,GORM 的钩子函数需要在结构体的指针接收者上定义,而不能在值接收者上定义。此外,GORM 使用的是结构体标签来定义表结构,需要注意标签的正确使用。

总体而言,GORM 是一个非常优秀的 ORM 库,其简单易用、功能强大、性能高效的特点使其在Go语言社区中得到了广泛的应用。在实际项目中,我们可以根据具体的需求选择不同的特性来进行灵活的开发,从而提高开发效率和代码质量。