仓储模式与事务查询

huangapple go评论88阅读模式
英文:

Repository pattern with transactional query

问题

我正在编写一个可以进行事务查询的服务(在这个问题中,我将使用GORM)。

UserService

type userService struct {
	UserRepository  repository.IUserRepository
	TokenRepository repository.ITokenRepository
}

type IUserService interface {
	WithTrx() IUserService
	CommitTrx() error
	RollbackTrx()

	Create(ctx context.Context, name string) (*model.User, error)
	// ...
	// ...
}

这是服务的一些实现。

user.go

func (s *userService) WithTrx() IUserService {
	newService := &userService{
		UserRepository:       s.UserRepository.WithTrx(),
		TokenRepository:      s.TokenRepository,
	}
	return newService
}

func (s *userService) Create(ctx context.Context, name string) (*model.User, error) {
	// ...
	// s.UserRepository.Create()
	// 然后返回用户和错误
	// ...
}

而对于UserRepository.WithTrx(),基本上只是返回接口本身。

type psqlUserRepository struct {
	DB *gorm.DB
}

type IUserRepository interface {
	WithTrx() IUserRepository
	CommitTrx() error
	RollbackTrx()

	Create(ctx context.Context, u model.User) (*model.User, error)
	// ...
}

func (r *psqlUserRepository) WithTrx() IUserRepository {
	return &psqlUserRepository{DB: r.DB.Begin()}
}

所以当我需要用户服务使用事务查询来创建用户时,我只需要:

trx := userserviceInstance.WithTrx()
user, err := trx.Create(ctx, name)
// 错误处理和回滚
commitErr := trx.CommitTrx()

是否有类似的方法?这被称为什么?我不确定这是否是创建事务查询的正确模式。

英文:

I am writing a service that can make a transactional query, (in this question I will be using GORM)

UserService

type userService struct {
	UserRepository  repository.IUserRepository
	TokenRepository repository.ITokenRepository
}

type IUserService interface {
WithTrx() IUserService
CommitTrx() error
RollbackTrx()

Create(ctx context.Context, name string) (*model.User, error)
...
...
}

here is some implementation of the service

user.go

func (s *userService) WithTrx() IUserService {
	newService := &userService{
		UserRepository:       s.UserRepository.WithTrx(),
		TokenRepository:      s.TokenRepository,
	
	}
	return newService
}
func (s *userService) Create(ctx context.Context, name string) (*model.User, error) {
... 
// s.UserRepository.Create() 
// then return the user, error 
...
}


and for the UserRepository.WithTrx() is basically just returning the interface itself

type psqlUserRepository struct {
	DB *gorm.DB
}

type IUserRepository interface {
	WithTrx() IUserRepository
	CommitTrx() error
	RollbackTrx()

	Create(ctx context.Context, u model.User) (*model.User, error)
...
}

func (r *psqlUserRepository) WithTrx() IUserRepository {
	return &psqlUserRepository{DB: r.DB.Begin()}
}

So when I need user service to create a user using transactional query, I just:


trx:= userserviceInstance.WithTrx()
user, err := trx.Create(ctx, name)
// err handling and rollback
commitErr := trx.CommitTrx()

Is there any similar approach like this? What is it called? I am not sure whether this is the right pattern to create a transactional query.

答案1

得分: 3

我猜这里有几个要点。

仓储模式通常用于隐藏存储的实现细节。

事务是一个技术细节,不应该暴露给更高层。

换句话说,你的仓储接口(架构元素)不应该暴露事务(技术细节)。

是否有类似的方法?它被称为什么?我不确定这是否是创建事务查询的正确模式。
你可以了解一下工作单元模式,它对你的目的可能有用。

你可以看一下工作单元模式。

以下是一些你可能会发现有用的示例:

英文:

I guess there are a few moments here.

The Repository pattern is normally used to hide the implementation details of a storage.

A Transaction is a technical detail which should not be exposed to the higher layers.

In other words the Repository interface (architectural element) you have shouldn't expose the transaction (technical details).

> Is there any similar approach like this? What is it called? I am not
> sure whether this is the right pattern to create a transactional query
You may want to learn more about Unit of Work pattern which can be useful for your purpose.

You may take a look at Unit of Work Pattern.

Bellow are some examples which you may find useful:

huangapple
  • 本文由 发表于 2021年7月6日 18:29:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/68268882.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定