Database DDD设计模式建议中的事务
正如我们所知,服务控制器/用例层负责处理业务逻辑, repo是用来处理数据库查询的 现在我有:Database DDD设计模式建议中的事务,database,go,transactions,domain-driven-design,go-gorm,Database,Go,Transactions,Domain Driven Design,Go Gorm,正如我们所知,服务控制器/用例层负责处理业务逻辑, repo是用来处理数据库查询的 现在我有: func (s *OrderService) Create(order models.Order) (models.Order, error) { ... user := models.User{ Contact: order.Address.Contact, } createdUser, err := s.UserRepo.Save(user) // err han
func (s *OrderService) Create(order models.Order) (models.Order, error) {
...
user := models.User{
Contact: order.Address.Contact,
}
createdUser, err := s.UserRepo.Save(user)
// err handling...
order.User = user
createdOrder, err := s.OrderRepo.save(order)
// err handling...
return order, nil
}
我希望应用gorm db。Begin transaction变得更加灵活,而不是我当前的代码过于静态。
那么我应该删除gorm.DB回购协议吗
一,。通过参数传入gorm.DB
tx := s.DB.Begin()
createdUser, err := s.UserRepo.Save(user, tx)
二,。或者直接在服务层运行查询??但它打破了ddd的设计理念
tx := s.DB.Begin()
createdUser, err := tx.Create(&user)
if err != nil {
tx.Rollback()
}
createdOrder, err := tx.Create(&order)
if err != nil {
tx.Rollback()
}
tx.Commit()
GORM调用绝对应该在存储层中保持抽象。若将事务句柄等实现细节泄露给业务逻辑,存储层将与特定的存储实现紧密耦合 在域驱动的世界中,人们可能应该以这样的方式对存储层的接口进行建模,即它具有使用域对象操作业务逻辑所需的所有操作,而不是数据库提供的基本操作。关键是,如果以后从SQL数据库切换到S3 REST API,则面向业务逻辑的接口将保持不变。因此,取而代之或在orderepo.Save之上,我还将创建orderepo.SaveAsNewUser Order,User,err,这将在内部利用数据库事务。根据DDD,事务不应跨越聚合边界 参考资料: 如果我们出于某种原因需要在事务中更新它们,您可能需要重新查看它们是否应该是某个聚合的一部分 在编写用于聚合的存储库时,可以将事务整齐地隐藏在存储库层中 我通常遵循以下界面
// holds the business logic to modify the aggregate, provided by business layer
type AggregateUpdateFunction func (a *Aggregate) error
type Repository interface {
Create(ctx context.Context, aggregate *Aggregate)
Read(ctx context.Context, id string) *Aggregate
// starts a read-modify-write cycle internally in a transaction
Update(ctx context.Context, id string, updateFunc AggregateUpdateFunction) error
}
// holds the business logic to modify the aggregate, provided by business layer
type AggregateUpdateFunction func (a *Aggregate) error
type Repository interface {
Create(ctx context.Context, aggregate *Aggregate)
Read(ctx context.Context, id string) *Aggregate
// starts a read-modify-write cycle internally in a transaction
Update(ctx context.Context, id string, updateFunc AggregateUpdateFunction) error
}