英文:
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
我猜这里有几个要点。
仓储模式通常用于隐藏存储的实现细节。
事务是一个技术细节,不应该暴露给更高层。
换句话说,你的仓储接口(架构元素)不应该暴露事务(技术细节)。
是否有类似的方法?它被称为什么?我不确定这是否是创建事务查询的正确模式。
你可以了解一下工作单元模式,它对你的目的可能有用。
你可以看一下工作单元模式。
以下是一些你可能会发现有用的示例:
- https://dev.to/techschoolguru/a-clean-way-to-implement-database-transaction-in-golang-2ba
 - https://goenning.net/2017/06/20/session-per-request-pattern-go/
 - https://pseudomuto.com/2018/01/clean-sql-transactions-in-golang/
 - https://github.com/screwyprof/skeleton/blob/main/internal/pkg/adapter/postgres/certificate_repository.go
 
英文:
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:
- https://dev.to/techschoolguru/a-clean-way-to-implement-database-transaction-in-golang-2ba
 - https://goenning.net/2017/06/20/session-per-request-pattern-go/
 - https://pseudomuto.com/2018/01/clean-sql-transactions-in-golang/
 - https://github.com/screwyprof/skeleton/blob/main/internal/pkg/adapter/postgres/certificate_repository.go
 
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论