1. 链式操作

1.1. 链式操作

Gorm 继承了链式操作接口, 所以你可以写像下面一样的代码:

  1. db, err := gorm.Open("postgres", "user=gorm dbname=gorm sslmode=disable")
  2. // 创建一个新的关系
  3. tx := db.Where("name = ?", "jinzhu")
  4. // 新增更多的筛选条件
  5. if someCondition {
  6. tx = tx.Where("age = ?", 20)
  7. } else {
  8. tx = tx.Where("age = ?", 30)
  9. }
  10. if yetAnotherCondition {
  11. tx = tx.Where("active = ?", 1)
  12. }

直到调用立即方法之前都不会产生查询,在某些场景中会很有用。

就像你可以封装一个包来处理一些常见的逻辑

1.2. 创建方法

创建方法就是那些会产生 SQL 查询并且发送到数据库,通常它就是一些 CRUD 方法, 就像:

Create, First, Find, Take, Save, UpdateXXX, Delete, Scan, Row, Rows

下面是一个创建方法的例子:

  1. tx.Find(&user)

生成

  1. SELECT * FROM users where name = 'jinzhu' AND age = 30 AND active = 1;

1.3. Scopes 方法

Scope 方法基于链式操作理论创建的。

使用它,你可以提取一些通用逻辑,写一些更可用的库。

  1. func AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
  2. return db.Where("amount > ?", 1000)
  3. }
  4. func PaidWithCreditCard(db *gorm.DB) *gorm.DB {
  5. return db.Where("pay_mode_sign = ?", "C")
  6. }
  7. func PaidWithCod(db *gorm.DB) *gorm.DB {
  8. return db.Where("pay_mode_sign = ?", "C")
  9. }
  10. func OrderStatus(status []string) func (db *gorm.DB) *gorm.DB {
  11. return func (db *gorm.DB) *gorm.DB {
  12. return db.Scopes(AmountGreaterThan1000).Where("status in (?)", status)
  13. }
  14. }
  15. db.Scopes(AmountGreaterThan1000, PaidWithCreditCard).Find(&orders)
  16. // 查找所有大于1000的信用卡订单和金额
  17. db.Scopes(AmountGreaterThan1000, PaidWithCod).Find(&orders)
  18. // 查找所有大于1000的 COD 订单和金额
  19. db.Scopes(AmountGreaterThan1000, OrderStatus([]string{"paid", "shipped"})).Find(&orders)
  20. // 查找大于1000的所有付费和运单

1.4. 多个创建方法

当使用 GORM 的创建方法,后面的创建方法将复用前面的创建方法的搜索条件(不包含内联条件)

  1. db.Where("name LIKE ?", "jinzhu%").Find(&users, "id IN (?)", []int{1, 2, 3}).Count(&count)

生成

  1. SELECT * FROM users WHERE name LIKE 'jinzhu%' AND id IN (1, 2, 3)
  2. SELECT count(*) FROM users WHERE name LIKE 'jinzhu%'

1.5. 线程安全

所有的链式操作都将会克隆并创建一个新的数据库对象(共享一个连接池),GORM 对于多个 goroutines 的并发使用是安全的。