快速入门
[[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.Model 与 orm.SoftDeletes 两个框架自带结构体,他们分别定义了 id, created_at, updated_at 与 deleted_at,其中 orm.SoftDeletes 代表模型开启了软删除功能。
模型约定
- 模型使用大驼峰命名;
- 使用模型的复数形式「蛇形命名」来作为表名;
例如,模型名称为 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,以实现超时控制等功能。
facades.Orm.WithContext(ctx)
指定数据库链接
如果你在配置文件 config/database.go 中定义了多个数据库连接,你可以通过 facades.Orm 的 Connection 方法来使用它们。传递给 Connection 方法的连接名称应该是在 config/database.go 配置的连接之一:
facades.Orm.Connection("mysql")
获取数据库实例
每次进行具体数据库操作前,都需要先获取数据库的实例。
facades.Orm.Query()facades.Orm.Connection("mysql").Query()facades.Orm.WithContext(ctx).Query()
查询
查询单条数据
var user models.Userfacades.Orm.Query().First(&user)// SELECT * FROM users WHERE id = 10;
根据 ID 查询单条或多条数据
var user models.Userfacades.Orm.Query().Find(&user, 1)// SELECT * FROM users WHERE id = 1;var users []models.Userfacades.Orm.Query().Find(&users, []int{1,2,3})// SELECT * FROM users WHERE id IN (1,2,3);
查询多条数据
var users []models.Userfacades.Orm.Query().Where("id in ?", []int{1,2,3}).Get(&users)// SELECT * FROM users WHERE id IN (1,2,3);
查找或创建
var user models.Userfacades.Orm.Query().Where("sex = ?", 1).FirstOrCreate(&user, models.User{Name: "tom"})// SELECT * FROM users where name="tom" and sex=1;// INSERT INTO users (name) VALUES ("tom");facades.Orm.Query().Where("sex = ?", 1).FirstOrCreate(&user, models.User{Name: "tom"}, , models.User{Avatar: "avatar"})// SELECT * FROM users where name="tom" and sex=1;// INSERT INTO users (name,avatar) VALUES ("tom", "avatar");
Where 条件
facades.Orm.Query().Where("name", "tom")facades.Orm.Query().Where("name = 'tom'")facades.Orm.Query().Where("name = ?", "tom")facades.Orm.Query().OrWhere("name = ?", "tom")
指定查询数量
var users []models.Userfacades.Orm.Query().Where("name = ?", "tom").Limit(3).Get(&users)// SELECT * FROM users WHERE name = "tom" LIMIT 3;
指定查询开始位置
var users []models.Userfacades.Orm.Query().Where("name = ?", "tom").Offset(5).Limit(3).Get(&users)// SELECT * FROM users WHERE name = "tom" OFFSET 5 LIMIT 3;
排序
var users []models.Userfacades.Orm.Query().Where("name = ?", "tom").Order("sort asc").Order("id desc").Get(&users)// SELECT * FROM users WHERE name = "tom" order sort asc, id desc;
查询单列
var ages []int64facades.Orm.Query().Model(&models.User{}).Pluck("age", &ages)// SELECT `name` FROM `users`;
指定表查询
如果想查询一些聚合数据,需要指定具体表。
使用模型指定
var count int64facades.Orm.Query().Model(&models.User{}).Count(&count)// SELECT count(1) where users
使用表名指定
var count int64facades.Orm.Query().Table("users").Count(&count)// SELECT count(1) where users
检索聚合
var count intfacades.Orm.Query().Where("name = ?", "tom").Count(&count)// SELECT count(1) FROM users WHERE name = 'tom'
指定查询列
Select 允许你指定从数据库中检索哪些字段,默认情况下,ORM 会检索所有字段。
facades.Orm.Query().Select("name", "age").Get(&users)// SELECT name, age FROM users;facades.Orm.Query().Select([]string{"name", "age"}).Get(&users)// SELECT name, age FROM users;
Group By & Having
type Result struct {Name stringTotal int}var result Resultfacades.Orm.Query().Model(&models.User{}).Select("name, sum(age) as total").Group("name").Having("name = ?", "tom").Get(&result)// SELECT name, sum(age) as total FROM `users` GROUP BY `name` HAVING name = "tom"
Join 查询
type Result struct {Name stringEmail string}var result Resultfacades.Orm.Query().Model(&models.User{}).Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&result)// SELECT users.name, emails.email FROM `users` left join emails on emails.user_id = users.id
创建
user := User{Name: "tom", Age: 18}result := facades.Orm.Query().Create(&user)// INSERT INTO users (name, age, created_at, updated_at) VALUES ("tom", 18, "2022-09-27 22:00:00", "2022-09-27 22:00:00");
批量创建
users := []User{{Name: "tom", Age: 18}, {Name: "tim", Age: 19}}result := facades.Orm.Query().Create(&users)
created_at和updated_at字段将会被自动填充。
更新
在现有模型基础上进行更新
var user models.Userfacades.Orm.Query().First(&user)user.Name = "tom"user.Age = 100facades.Orm.Query().Save(&user)// UPDATE users SET name='tom', age=100, updated_at = '2022-09-28 16:28:22' WHERE id=1;
更新单一字段
facades.Orm.Query().Model(&models.User{}).Where("name = ?", "tom").Update("name", "hello")// UPDATE users SET name='tom', updated_at='2022-09-28 16:29:39' WHERE name="tom";
更新多个字段
facades.Orm.Query().Model(&user).Where("name = ?", "tom").Updates(User{Name: "hello", Age: 18})// UPDATE users SET name="hello", age=18, updated_at = '2022-09-28 16:30:12' WHERE name = "tom";
updated_at字段将会被自动更新。
删除
根据模型删除
var user models.Userfacades.Orm.Query().Find(&user, 1)facades.Orm.Query().Delete(&user)// DELETE FROM users where id = 1;
根据 ID 删除
facades.Orm.Query().Delete(&models.User{}, 10)// DELETE FROM users WHERE id = 10;facades.Orm.Query().Delete(&models.User{}, []uint{1, 2, 3})// DELETE FROM users WHERE id in (1, 2, 3);
批量删除
facades.Orm.Query().Where("name = ?", "tom").Delete(&models.User{})// DELETE FROM users where name = "tom";
如果模型开启了软删除功能,想要强制删除某数据
facades.Orm.Query().Where("name = ?", "tom").ForceDelete(&models.User{})
如果在没有任何条件的情况下执行批量删除,ORM 不会执行该操作,并返回错误。对此,你必须加一些条件,或者使用原生 SQL。
查询软删除
var user models.Userfacades.Orm.Query().WithTrashed().First(&user)
过滤重复
var users []models.Userfacades.Orm.Query().Distinct("name").Find(&users)
执行原生查询 SQL
type Result struct {ID intName stringAge int}var result Resultdb.Raw("SELECT id, name, age FROM users WHERE name = ?", "tom").Scan(&result)
执行原生更新 SQL
facades.Orm.Query().Exec("DROP TABLE users")// DROP TABLE users;
事务
可以使用 Transaction 方法执行事务:
import ("github.com/goravel/framework/contracts/database/orm""github.com/goravel/framework/facades""goravel/app/models")...return facades.Orm.Transaction(func(tx orm.Transaction) error {var user models.Userreturn tx.Find(&user, user.ID)})
也可以自己手动控制事务的流程:
tx, err := facades.Orm.Query().Begin()user := models.User{Name: "Goravel"}if err := tx.Create(&user); err != nil {err := tx.Rollback()} else {err := tx.Commit()}
Scopes
允许你指定常用的查询,可以在调用方法时引用这些查询。
func Paginator(page string, limit string) func(methods orm.Query) orm.Query {return func(query orm.Query) orm.Query {page, _ := strconv.Atoi(page)limit, _ := strconv.Atoi(limit)offset := (page - 1) * limitreturn query.Offset(offset).Limit(limit)}}facades.Orm.Query().Scopes(scopes.Paginator(page, limit)).Find(&entries)
