Skip to content

仓库

介绍

仓库数据层的一部分。它们实现将被调用来处理数据(获取、创建、更新、删除等)的方法,并将使用模型模型是数据库模式的 Go 表示。模型的实例是单个数据库记录。

仓库不应依赖于服务,但可以依赖于其他仓库。因此,它必须仅与数据库交互:其目的是执行数据操作所需的单元数据库操作。不应在仓库中实现任何业务逻辑。

例如,如果我们有一个跟踪用户操作(用户历史记录)的系统,并且我们希望在使用者创建其帐户时创建“注册”历史记录条目,我们将有两个不相互依赖的仓库:

  • user.Create 方法应创建用户,而不是关联的历史记录条目。
  • history.Create 方法应创建历史记录条目。

这是服务的工作,使用事务来处理这些场景。

模型

模型在 database/model 包中定义。每个资源都有自己的文件。模型通常只是普通的 Golang 结构体、基本 Go 类型或它们的指针。也支持 sql.Scannerdriver.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)
}