快速入门

[[toc]]

介绍

Goravel 提供了一套非常简单易用的数据库交互方式,开发者可以使用 facades.Orm 进行操作。目前,Goravel 为以下四种数据库提供了官方支持:

  • MySQL 5.7+
  • PostgreSQL 9.6+
  • SQLite 3.8.8+
  • SQL Server 2017+

在开始之前,请在 .env 文件中配置数据库链接信息,并确认 config/database.go 的默认配置。

配置

数据库的配置文件在 config/database.go 文件中。你可以在这个文件中配置所有的数据库连接,并指定默认的数据库连接。该文件中的大部分配置都基于项目的环境变量,且提供了 Goravel 所支持的数据库配置示例。

模型

模型相当于数据表的映射,你可以根据框架自带的模型文件 app/models/user.go 创建自定义模型。在 app/models/user.go 文件中 struct 嵌套了 orm.Modelorm.SoftDeletes 两个框架自带结构体,他们分别定义了 id, created_at, updated_atdeleted_at,其中 orm.SoftDeletes 代表模型开启了软删除功能。

模型约定

  1. 模型使用大驼峰命名;
  2. 使用模型的复数形式「蛇形命名」来作为表名;

例如,模型名称为 UserOrder,则表名为 user_orders

facades.Orm 可用方法

方法名 作用
Connection 指定数据库链接
Query 获取数据库实例
Transaction 事务
WithContext 注入 Context

facades.Orm.Query & facades.Orm.Transaction 可用方法

方法名 作用
Begin 手动开始事务
Commit 提交事务
Count 数据库事务
Create 创建数据
Delete 删除数据
Distinct 过滤重复
Exec 执行原生更新 SQL
Find 获取一条数据
First 获取一条数据
FirstOrCreate 获取或创建一条数据
ForceDelete 强制删除
Get 获取多条数据
Group Group 查询
Having Having 查询
Join Join 查询
Limit 指定查询数量
Model 指定模型
Offset 指定查询开始位置
Order 排序
OrWhere 查询条件
Pluck 查询单列
Raw 执行原生查询 SQL
Rollback 手动回滚事务
Save 保存修改
Scan 将数据解析到 struct
Scopes Scopes
Select 指定查询列
Table 指定表
Update 更新单个字段
Updates 更新多个字段
Where 查询条件
WithTrashed 查询软删除

查询构造器

注入 Context

注入 Context,以实现超时控制等功能。

  1. facades.Orm.WithContext(ctx)

指定数据库链接

如果你在配置文件 config/database.go 中定义了多个数据库连接,你可以通过 facades.OrmConnection 方法来使用它们。传递给 Connection 方法的连接名称应该是在 config/database.go 配置的连接之一:

  1. facades.Orm.Connection("mysql")

获取数据库实例

每次进行具体数据库操作前,都需要先获取数据库的实例。

  1. facades.Orm.Query()
  2. facades.Orm.Connection("mysql").Query()
  3. facades.Orm.WithContext(ctx).Query()

查询

查询单条数据

  1. var user models.User
  2. facades.Orm.Query().First(&user)
  3. // SELECT * FROM users WHERE id = 10;

根据 ID 查询单条或多条数据

  1. var user models.User
  2. facades.Orm.Query().Find(&user, 1)
  3. // SELECT * FROM users WHERE id = 1;
  4. var users []models.User
  5. facades.Orm.Query().Find(&users, []int{1,2,3})
  6. // SELECT * FROM users WHERE id IN (1,2,3);

查询多条数据

  1. var users []models.User
  2. facades.Orm.Query().Where("id in ?", []int{1,2,3}).Get(&users)
  3. // SELECT * FROM users WHERE id IN (1,2,3);

查找或创建

  1. var user models.User
  2. facades.Orm.Query().Where("sex = ?", 1).FirstOrCreate(&user, models.User{Name: "tom"})
  3. // SELECT * FROM users where name="tom" and sex=1;
  4. // INSERT INTO users (name) VALUES ("tom");
  5. facades.Orm.Query().Where("sex = ?", 1).FirstOrCreate(&user, models.User{Name: "tom"}, , models.User{Avatar: "avatar"})
  6. // SELECT * FROM users where name="tom" and sex=1;
  7. // INSERT INTO users (name,avatar) VALUES ("tom", "avatar");

Where 条件

  1. facades.Orm.Query().Where("name", "tom")
  2. facades.Orm.Query().Where("name = 'tom'")
  3. facades.Orm.Query().Where("name = ?", "tom")
  4. facades.Orm.Query().OrWhere("name = ?", "tom")

指定查询数量

  1. var users []models.User
  2. facades.Orm.Query().Where("name = ?", "tom").Limit(3).Get(&users)
  3. // SELECT * FROM users WHERE name = "tom" LIMIT 3;

指定查询开始位置

  1. var users []models.User
  2. facades.Orm.Query().Where("name = ?", "tom").Offset(5).Limit(3).Get(&users)
  3. // SELECT * FROM users WHERE name = "tom" OFFSET 5 LIMIT 3;

排序

  1. var users []models.User
  2. facades.Orm.Query().Where("name = ?", "tom").Order("sort asc").Order("id desc").Get(&users)
  3. // SELECT * FROM users WHERE name = "tom" order sort asc, id desc;

查询单列

  1. var ages []int64
  2. facades.Orm.Query().Model(&models.User{}).Pluck("age", &ages)
  3. // SELECT `name` FROM `users`;

指定表查询

如果想查询一些聚合数据,需要指定具体表。

使用模型指定

  1. var count int64
  2. facades.Orm.Query().Model(&models.User{}).Count(&count)
  3. // SELECT count(1) where users

使用表名指定

  1. var count int64
  2. facades.Orm.Query().Table("users").Count(&count)
  3. // SELECT count(1) where users

检索聚合

  1. var count int
  2. facades.Orm.Query().Where("name = ?", "tom").Count(&count)
  3. // SELECT count(1) FROM users WHERE name = 'tom'

指定查询列

Select 允许你指定从数据库中检索哪些字段,默认情况下,ORM 会检索所有字段。

  1. facades.Orm.Query().Select("name", "age").Get(&users)
  2. // SELECT name, age FROM users;
  3. facades.Orm.Query().Select([]string{"name", "age"}).Get(&users)
  4. // SELECT name, age FROM users;

Group By & Having

  1. type Result struct {
  2. Name string
  3. Total int
  4. }
  5. var result Result
  6. facades.Orm.Query().Model(&models.User{}).Select("name, sum(age) as total").Group("name").Having("name = ?", "tom").Get(&result)
  7. // SELECT name, sum(age) as total FROM `users` GROUP BY `name` HAVING name = "tom"

Join 查询

  1. type Result struct {
  2. Name string
  3. Email string
  4. }
  5. var result Result
  6. facades.Orm.Query().Model(&models.User{}).Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&result)
  7. // SELECT users.name, emails.email FROM `users` left join emails on emails.user_id = users.id

创建

  1. user := User{Name: "tom", Age: 18}
  2. result := facades.Orm.Query().Create(&user)
  3. // INSERT INTO users (name, age, created_at, updated_at) VALUES ("tom", 18, "2022-09-27 22:00:00", "2022-09-27 22:00:00");

批量创建

  1. users := []User{{Name: "tom", Age: 18}, {Name: "tim", Age: 19}}
  2. result := facades.Orm.Query().Create(&users)

created_atupdated_at 字段将会被自动填充。

更新

在现有模型基础上进行更新

  1. var user models.User
  2. facades.Orm.Query().First(&user)
  3. user.Name = "tom"
  4. user.Age = 100
  5. facades.Orm.Query().Save(&user)
  6. // UPDATE users SET name='tom', age=100, updated_at = '2022-09-28 16:28:22' WHERE id=1;

更新单一字段

  1. facades.Orm.Query().Model(&models.User{}).Where("name = ?", "tom").Update("name", "hello")
  2. // UPDATE users SET name='tom', updated_at='2022-09-28 16:29:39' WHERE name="tom";

更新多个字段

  1. facades.Orm.Query().Model(&user).Where("name = ?", "tom").Updates(User{Name: "hello", Age: 18})
  2. // UPDATE users SET name="hello", age=18, updated_at = '2022-09-28 16:30:12' WHERE name = "tom";

updated_at 字段将会被自动更新。

删除

根据模型删除

  1. var user models.User
  2. facades.Orm.Query().Find(&user, 1)
  3. facades.Orm.Query().Delete(&user)
  4. // DELETE FROM users where id = 1;

根据 ID 删除

  1. facades.Orm.Query().Delete(&models.User{}, 10)
  2. // DELETE FROM users WHERE id = 10;
  3. facades.Orm.Query().Delete(&models.User{}, []uint{1, 2, 3})
  4. // DELETE FROM users WHERE id in (1, 2, 3);

批量删除

  1. facades.Orm.Query().Where("name = ?", "tom").Delete(&models.User{})
  2. // DELETE FROM users where name = "tom";

如果模型开启了软删除功能,想要强制删除某数据

  1. facades.Orm.Query().Where("name = ?", "tom").ForceDelete(&models.User{})

如果在没有任何条件的情况下执行批量删除,ORM 不会执行该操作,并返回错误。对此,你必须加一些条件,或者使用原生 SQL。

查询软删除

  1. var user models.User
  2. facades.Orm.Query().WithTrashed().First(&user)

过滤重复

  1. var users []models.User
  2. facades.Orm.Query().Distinct("name").Find(&users)

执行原生查询 SQL

  1. type Result struct {
  2. ID int
  3. Name string
  4. Age int
  5. }
  6. var result Result
  7. db.Raw("SELECT id, name, age FROM users WHERE name = ?", "tom").Scan(&result)

执行原生更新 SQL

  1. facades.Orm.Query().Exec("DROP TABLE users")
  2. // DROP TABLE users;

事务

可以使用 Transaction 方法执行事务:

  1. import (
  2. "github.com/goravel/framework/contracts/database/orm"
  3. "github.com/goravel/framework/facades"
  4. "goravel/app/models"
  5. )
  6. ...
  7. return facades.Orm.Transaction(func(tx orm.Transaction) error {
  8. var user models.User
  9. return tx.Find(&user, user.ID)
  10. })

也可以自己手动控制事务的流程:

  1. tx, err := facades.Orm.Query().Begin()
  2. user := models.User{Name: "Goravel"}
  3. if err := tx.Create(&user); err != nil {
  4. err := tx.Rollback()
  5. } else {
  6. err := tx.Commit()
  7. }

Scopes

允许你指定常用的查询,可以在调用方法时引用这些查询。

  1. func Paginator(page string, limit string) func(methods orm.Query) orm.Query {
  2. return func(query orm.Query) orm.Query {
  3. page, _ := strconv.Atoi(page)
  4. limit, _ := strconv.Atoi(limit)
  5. offset := (page - 1) * limit
  6. return query.Offset(offset).Limit(limit)
  7. }
  8. }
  9. facades.Orm.Query().Scopes(scopes.Paginator(page, limit)).Find(&entries)