Gorm CRUD操作详解

1,844 阅读3分钟

1. 创建操作

db.Create()

  1. 创建单条记录
user := User{Name: "Suta", Birthday: time.Now()}

result := db.Create(&user) // 通过数据的指针来创建

返回的result是一个gorm.DB对象,后续文章我们会详细讲解这个对象,这里我们只需要知道他会携带一些我们连接数据库执行SQL需要的信息以及执行之后返回的信息就足够了。

另外,db.Create()会为&user回填主键的值。

  1. 批量插入

可以借助一个切片实现批量插入的操作:

var users = []User{
        {Name: "suta1"}, 
        {Name: "suta2"}, 
        {Name: "suta3"}
    } 
db.Create(&users)
  1. 借助 map 创建
db.Model(&User{}).Create(
    []map[string]interface{}{
      {"Name": "suta1", "Age": 18},
      {"Name": "suta2", "Age": 20},
    })

db.Select() / db.Omit()

db.Select()db.Omit()都可以配合db.Create()使用:

  • db.Select()是指定需要更新的列
  • db.Omit()是指定不需要更新的列
db.Select("Name", "Age", "CreatedAt").Create(&user)

db.Omit("Name", "Age", "CreatedAt").Create(&user)

db.Model()

可以通过db.Model()方法制定Model结构,方便直接关联数据库表:

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

db.Clauses()

可以通过db.Clauses()配置增加操作导致冲突时的解决策略:

db.Clauses(clause.Locking{Strength: "UPDATE"}).Find(&users)

2. 查询操作

db.First() / db.Take() / db.Last()

db.First() db.Take() db.Last()均为单条查询语句:

  • db.First()查询第一条
  • db.Take()查询随机的一条
  • db.Last()查询最后一条
// 获取第一条记录(主键升序)
db.First(&user)
// SELECT * FROM users ORDER BY id LIMIT 1;

// 获取一条记录,没有指定排序字段
db.Take(&user)
// SELECT * FROM users LIMIT 1;

// 获取最后一条记录(主键降序)
db.Last(&user)
// SELECT * FROM users ORDER BY id DESC LIMIT 1;

db.Table()

提供类似于SQL中的FROM操作,但是需要注意,与db.First() db.Last()配合时,需要使用db.Model(),因为db.First() db.Last()需要对主键进行排序:

var user User

// 可以
result := map[string]interface{}{}
db.Model(&User{}).First(&result)
// SELECT * FROM `users` ORDER BY `users`.`id` LIMIT 1

// 不行
result := map[string]interface{}{}
db.Table("users").First(&result)

db.Find()

db.Find()可以检索所有记录:

result := db.Find(&users)
// SELECT * FROM users;

db.Where().Or()

相当于SQL中的条件查询

db.Not()

相当于SQL中的NOT

db.Order()

db.Order("age desc, name").Find(&users)
// SELECT * FROM users ORDER BY age desc, name;

// 多个 order
db.Order("age desc").Order("name").Find(&users)
// SELECT * FROM users ORDER BY age desc, name;

db.Limit().Offset()

db.Limit() db.Offset()两个方法是分页查询:

  • db.Limit()是限制页的容量
  • db.Offset()是规定跳过的数据量
db.Limit(10).Offset(5).Find(&users) 
// SELECT * FROM users OFFSET 5 LIMIT 10;

db.Group().Having()

实现分组查询:

db.Model(&User{})
.Select("name, sum(age) as total")
.Where("name LIKE ?", "group%")
.Group("name")
.First(&result)
// SELECT name, sum(age) as total 
// FROM `users` 
// WHERE name 
// LIKE "group%" 
// GROUP BY `name`

db.Scan() / db.Rows()

返回查询结果:

  • db.Scan(&ptr)将结果保存到&ptr
  • db.Rows()返回一个*sql.Row,可以通过.Next()遍历
type Result struct {
  Name string
  Age  int
}

var result Result
db.Table("users")
.Select("name", "age")
.Where("name = ?", "Antonio")
.Scan(&result)

rows, err := db.Table("users").Select("users.name, emails.email").Rows()
for rows.Next() { ... }

3. 更新操作

db.Save() / db.Update() / dp.Updates()

  • db.Save() 会保存所有的字段,即使字段是零值
  • db.Update()只会更新非零值的字段
  • db.Updates()只会更新非零值的字段

db.Save(&user{Name: suta, Age: 00})

db.Model(&User{}).Where("active = ?", true).Update("name", "hello")
// UPDATE users 
// SET name='hello', updated_at='2013-11-17 21:34:10' 
// WHERE active=true;

dp.UpdateColume()

使用SQL表达式更新列:

db.Model(&product).UpdateColumn("quantity", gorm.Expr("quantity - ?", 1))
// UPDATE "products" SET "quantity" = quantity - 1 WHERE "id" = 3;

4. 删除操作

db.Delete()

如果在没有任何条件的情况下执行批量删除,GORM 不会执行该操作,并返回 ErrMissingWhereClause 错误

db.Where("email LIKE ?", "%jinzhu%").Delete(Email{})
// DELETE from emails where email LIKE "%jinzhu%";

db.Delete(&User{}).Error // gorm.ErrMissingWhereClause

db.Where("1 = 1").Delete(&User{}) 
// DELETE FROM `users` WHERE 1=1

软删除

如果您的模型包含了一个 gorm.deletedat 字段(gorm.Model 已经包含了该字段),它将自动获得软删除的能力!

拥有软删除能力的模型调用 Delete 时,记录不会被从数据库中真正删除。但 GORM 会将 DeletedAt 置为当前时间, 并且你不能再通过正常的查询方法找到该记录。

可以使用 db.Unscoped() 找到被软删除的记录。

db.Unscoped().Where("age = 20").Find(&users)
// SELECT * FROM users WHERE age = 20;

也可以使用 Unscoped 永久删除匹配的记录.

db.Unscoped().Delete(&order) 
// DELETE FROM orders WHERE id=10;

本文正在参加技术专题18期-聊聊Go语言框架