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)
查询单条记录
可以使用 First、Take 或 Last 方法来查询单条记录,这些方法默认按主键排序,并根据不同的条件进行筛选:
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 提供了多种更新方法,例如 Update、Updates 和 Save。可以根据需求选择更新某个字段、多字段或整个记录。
更新单个字段
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 的编写并增强了代码的可读性。