GORM 使用指南:Go 语言的 ORM 库与数据库交互| 豆包MarsCode AI 刷题

314 阅读4分钟

使用 GORM 连接数据库

ORM (Object-Relational Mapping) 是一种程序设计技术,用于在关系数据库和面向对象的编程语言之间转换数据。GORM 是 Go 的一款常用 ORM 库,能够简化数据库的交互,通过映射 Go 结构体与数据库表,实现对象与关系型数据库之间的转换。


安装 GORM

在 Go 项目中使用 GORM 需要通过 go get 安装:

go get -u gorm.io/gorm

同时,如果使用 MySQL,安装 MySQL 的驱动:

go get -u gorm.io/driver/mysql

定义模型

GORM 通过将 Go 结构体映射到数据库表来简化数据库交互。可以通过定义结构体来表示数据库表。下面是一个简单的例子:

定义结构体
type Student struct {
	ID    uint   `gorm:"primaryKey"` //作为主键
	Name  string `gorm:"size:255"`
	Class int    `gorm:"column:班级"`
	Score int    `gorm:"default:0"`
}

在这个结构体中,gorm.Model 包含了 IDCreatedAtUpdatedAtDeletedAt(支持软删除)字段。NameSum 是自定义的字段。

自定义表名

通过实现 TableName 接口,GORM 会默认根据结构体名生成表名,如果需要自定义表名,可以实现该接口:

func (s Student) TableName() string {
	return "students"
}
自定义主键与软删除支持

GORM 会自动为结构体生成 ID 作为主键。如果需要自定义主键或进行软删除(使用 DeletedAt 字段),可以如下配置:

type Model struct {
    ID        uint       `gorm:"primarykey"`
    CreatedAt time.Time
    UpdatedAt time.Time
    DeletedAt gorm.DeletedAt `gorm:"index"` // 支持软删除
}

连接数据库

通过 gorm.Open 方法连接数据库,并通过 AutoMigrate 自动迁移数据库表结构。下面是连接 MySQL 数据库并自动创建表的示例:

dsn := "user:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
    panic("failed to connect database")
}

// 自动迁移表结构
err = db.AutoMigrate(&Plant{})
if err != nil {
    log.Fatalf("Failed to migrate database: %v", err)
}

创建记录

插入数据

通过 Create 方法插入单条或多条记录:

s1 := []*Student{
    {ID: 1, Name: "Zhang", Class: 2024},
    {ID: 2, Name: "Li", Class: 2023, Score: 100},
    {ID: 3, Name: "Wang", Class: 2022, Score: 90},
}
db.Create(s1) // 插入数据,传入结构体指针

使用 Upsert(插入或更新)

GORM 支持 Upsert,即如果记录已存在则更新,否则插入。可以通过 OnConflict 子句来解决冲突:

result := db.Clauses(clause.OnConflict{
    Columns:   []clause.Column{{Name: "ID"}}, // 指定冲突的列
    DoUpdates: clause.AssignmentColumns([]string{"Score"}), // 更新的字段
}).Create(&s2)

if result.Error != nil {
    log.Println(result.Error)
}

查询记录

查询单个记录

使用 FirstTakeLast 查询一条记录:

var s3 Student
db.First(&s3, 3) // 根据主键查询
fmt.Println(s3)

var s4 Student
db.Where("Score =?", 100).First(&s4) // 条件查询
fmt.Println(s4)

查询多个记录

使用 Find 查询多条记录:

var s5 []Student
db.Where("Score > ?", 0).Find(&s5) // 查询所有成绩大于 0 的学生

var s6 []Student
db.Where("Score > ? AND Class = ?", 0, 2024).Find(&s6) // 条件查询
fmt.Println(s5, s6)

查询某些字段

只查询某些字段,可以通过 Select 来实现:

var names []string
db.Model(&Student{}).Select("Name").Where("Class = ?", 2024).Pluck("Name", &names)
fmt.Println(names)

更新数据

更新特定字段

通过 Updates 方法更新指定字段:

db.Where("name = ?", "qi").Updates(Student{Score: 95}) // 部分字段更新

也可以使用 map 更新字段:

db.Where("name = ?", "Li").Updates(map[string]interface{}{"score": 95})

更新所有字段

使用 Save 方法更新记录(包括所有字段):

var s3 Student
db.First(&s3, 3) // 根据主键查询
s3.Class = 2025
s3.Name = "qi"
db.Save(&s3) // 全字段更新

删除记录

物理删除

物理删除通过 Delete 方法:

db.Delete(&Student{}, 1) // 根据主键删除
软删除

软删除通过 Delete 方法,要求表中有 DeletedAt 字段:

db.Delete(&Student{}, 1) // 软删除

// 忽略软删除,进行硬删除
db.Unscoped().Delete(&Student{}, 1)

删除时,GORM 会自动将 DeletedAt 字段设置为当前时间,从而不删除实际数据,保持数据完整性。

Hooks

GORM 支持模型钩子,可以在创建、更新或删除记录时执行自定义逻辑。常用的钩子有:

  • BeforeCreate: 在创建记录之前调用。
  • AfterCreate: 在创建记录之后调用。
  • BeforeUpdate: 在更新记录之前调用。
  • AfterUpdate: 在更新记录之后调用。
  • BeforeDelete: 在删除记录之前调用。
  • AfterDelete: 在删除记录之后调用。

例如,定义 BeforeCreate 钩子:

func (p *Student) BeforeCreate(tx *gorm.DB) (err error) {
    // 在创建记录之前,执行某些逻辑
    if p.Name == "" {
        return errors.New("Name cannot be empty")
    }
    return
}

其他高级功能

事务处理

GORM 支持事务操作,可以通过 BeginCommitRollback 方法来控制事务:

tx := db.Begin()

if err := tx.Create(&student).Error; err != nil {
    tx.Rollback()
    return err
}

tx.Commit()

关联查询

GORM 支持关联查询(如一对多、多对多关系等)。例如,定义一对多关系:

type Course struct {
    ID       uint
    Name     string
    Students []Student
}

db.Preload("Students").Find(&courses)

以上示例加载了 Course 表中的所有数据,并预加载了与每个课程相关联的 Students 数据。

分页查询

GORM 也支持分页查询,可以使用 LimitOffset 来实现:

var students []Student
db.Where("Class = ?", 2024).Limit(10).Offset(20).Find(&students)

总结

GORM 是一个强大且灵活的 ORM 库,它使 Go 开发者能够轻松地与关系型数据库进行交互。通过其简洁的 API 和丰富的功能,GORM 让数据库操作变得更加直观和高效。无论是基本的增、删、改、查操作,还是更复杂的事务管理、关联查询等功能,都可以通过 GORM 实现。