使用GORM实现增删改查 | 豆包MarsCode AI刷题

148 阅读3分钟

1. 定义模型

在 GORM 中,模型是用来映射数据库表的结构体,通常每个结构体对应一张数据库表,每个结构体的字段对应表中的一列。可以通过标签控制字段的属性,比如列名、索引等。

type User struct {
    ID        uint   `gorm:"primaryKey"`          // 主键
    Name      string `gorm:"size:100"`            // 名称字段,最大长度 100
    Email     string `gorm:"uniqueIndex"`         // 邮箱字段,唯一索引
    Age       int                                 // 年龄字段
    CreatedAt time.Time                           // 创建时间
}

以上结构体定义了一个 User 模型,并将其映射为数据库表,通过 GORM 的标签进一步控制字段的属性。gorm:"primaryKey" 声明主键,gorm:"uniqueIndex" 创建唯一索引。


2. 创建记录(Create)

可以使用 db.Create() 方法来创建新记录,传入的对象会自动映射为插入语句。db.Create() 支持批量插入,可以传入结构体切片。

// 单条插入
user := User{Name: "Alice", Email: "alice@example.com", Age: 25}
db.Create(&user)

// 批量插入
users := []User{
    {Name: "Bob", Email: "bob@example.com", Age: 30},
    {Name: "Charlie", Email: "charlie@example.com", Age: 28},
}
db.Create(&users)

Create 会在插入后自动填充对象中的主键值(例如 ID),方便后续使用。


3. 查询记录(Read)

查询单条记录

可以使用 FirstTakeLast 方法来查询单条记录,这些方法默认按主键排序,并根据不同的条件进行筛选:

var user User
db.First(&user, 1)                         // 根据主键查询,ID = 1
db.First(&user, "email = ?", "alice@example.com") // 根据条件查询

查询多条记录

Find 方法用于查询多条记录,可以结合条件和链式调用进一步控制查询。

var users []User
db.Where("age > ?", 20).Find(&users)       // 查询年龄大于 20 的用户
db.Order("age desc").Find(&users)          // 按年龄降序排序查询所有用户

4. 更新记录(Update)

GORM 提供了多种更新方法,例如 UpdateUpdatesSave。可以根据需求选择更新某个字段、多字段或整个记录。

更新单个字段

db.Model(&user).Update("Age", 26)           // 更新单个字段

更新多个字段

db.Model(&user).Updates(User{Name: "Alice A", Age: 27}) // 批量更新字段
db.Model(&user).Updates(map[string]interface{}{"Name": "Alice A", "Age": 27}) // 使用 map 更新字段

Updates 可以通过结构体或 map 的方式进行字段更新。需要注意,Updates 方法不会更新零值字段(如空字符串、0、false 等)。

批量更新

GORM 支持批量更新,可以通过 Where 条件实现批量更新。

db.Model(&User{}).Where("age < ?", 25).Update("age", 25) // 将年龄小于 25 的用户更新为 25

5. 删除记录(Delete)

删除操作可以通过 Delete 方法完成,支持按主键删除、按条件删除,以及软删除。

删除单个记录

db.Delete(&user, 1)                        // 根据主键删除记录,ID = 1

按条件删除

db.Where("age > ?", 30).Delete(&User{})    // 删除年龄大于 30 的用户

软删除

GORM 支持软删除,通过添加 gorm.DeletedAt 字段,可以在删除时将 DeletedAt 设置为当前时间,而非实际删除数据。

type User struct {
    gorm.Model          // 默认包含 ID、CreatedAt、UpdatedAt 和 DeletedAt 字段
    Name      string
    Email     string
    Age       int
}

调用 Delete 时会自动触发软删除,查询时默认忽略已软删除的记录。


6. 关联关系

GORM 支持多种关联关系,如一对多、多对多等,通过标签配置实现。

一对多

type Company struct {
    ID      uint
    Name    string
    Users   []User  `gorm:"foreignKey:CompanyID"`
}
type User struct {
    ID        uint
    Name      string
    CompanyID uint
}

查询时可以使用 Preload 预加载关联数据:

var company Company
db.Preload("Users").First(&company)

7. 事务(Transactions)

GORM 提供了事务支持,可以使用 db.Transaction 包裹多个操作,以实现原子性。

err := db.Transaction(func(tx *gorm.DB) error {
    if err := tx.Create(&user).Error; err != nil {
        return err
    }
    if err := tx.Create(&order).Error; err != nil {
        return err
    }
    return nil
})
if err != nil {
    log.Fatalf("Transaction failed: %v", err)
}

8. 高级查询

GORM 提供了丰富的链式查询操作,如分组、聚合、子查询等。

分组和聚合

var results []Result
db.Model(&User{}).Select("age, count(*) as count").Group("age").Scan(&results)

子查询

subQuery := db.Model(&Order{}).Select("user_id").Where("amount > ?", 100)
db.Where("id IN (?)", subQuery).Find(&users)

结语

通过 GORM 可以轻松实现 Go 应用中的数据库操作,简化了 SQL 的编写并增强了代码的可读性。