仓库
介绍
仓库是数据层的一部分。它们实现将被调用来处理数据(获取、创建、更新、删除等)的方法,并将使用模型。模型是数据库模式的 Go 表示。模型的实例是单个数据库记录。
仓库不应依赖于服务,但可以依赖于其他仓库。因此,它必须仅与数据库交互:其目的是执行数据操作所需的单元数据库操作。不应在仓库中实现任何业务逻辑。
例如,如果我们有一个跟踪用户操作(用户历史记录)的系统,并且我们希望在使用者创建其帐户时创建“注册”历史记录条目,我们将有两个不相互依赖的仓库:
user.Create
方法应仅创建用户,而不是关联的历史记录条目。history.Create
方法应仅创建历史记录条目。
这是服务的工作,使用事务来处理这些场景。
模型
模型在 database/model
包中定义。每个资源都有自己的文件。模型通常只是普通的 Golang 结构体、基本 Go 类型或它们的指针。也支持 sql.Scanner
和 driver.Valuer
接口。
示例:
go
// database/model/user.go
package model
import (
"time"
"gopkg.in/guregu/null.v4"
"gorm.io/gorm"
)
type User struct {
ID int64 `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt null.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
Email string `gorm:"uniqueIndex"`
}
func (User) TableName() string {
return "users"
}
INFO
建议始终定义一个 TableName()
方法。
TIP
有关模型定义的更多信息,请参阅 Gorm 的文档。
实现
每个仓库在 database/repository
中应有自己的文件,以其使用的资源命名,使用单数形式。
完整示例:
go
// database/repository/user.go
package repository
import (
"context"
"gorm.io/gorm"
"goyave.dev/goyave/v5/database"
"goyave.dev/goyave/v5/util/errors"
"goyave.dev/template/database/model"
)
// User 仓库用于数据库中的用户操作。
type User struct {
DB *gorm.DB
}
// NewUser 创建一个新的用户仓库。
func NewUser(db *gorm.DB) *User {
return &User{
DB: db,
}
}
// Paginate 在执行后返回一个分页器。
func (r *User) Paginate(ctx context.Context, page int, pageSize int) (*database.Paginator[*model.User], error) {
users := []*model.User{}
paginator := database.NewPaginator(r.DB, page, pageSize, &users)
err := paginator.Find()
return paginator, err
}
// First 返回由给定 ID 标识的用户,或 `nil`
func (r *User) First(ctx context.Context, id int64) (*model.User, error) {
var user *model.User
db := r.DB.Where("id", id).First(&user)
return user, errors.New(db.Error)
}