英文:
Gorm Transaction Error error = transaction has already been committed or rolled back
问题
我正在尝试在下面的代码中进行事务管理。如果其中一个策略出现错误,我尝试进行回滚操作。在测试代码时,我注意到如果回滚或提交命令成功执行一次,第二次执行时会出现错误,提示"事务已经被提交或回滚"。我该如何解决这个错误?
func (d *DistributeService) Distribute(vehicleNumberPlate string, request model.DistributeRequest) (*model.DistributeResponse, error) {
var response model.DistributeResponse
response.Vehicle = vehicleNumberPlate
var routeList []model.RouteResponse
tx := d.repo.BeginTransaction()
for _, routes := range request.RouteRequest {
var routeResponse model.RouteResponse
strategy, isStrategyExists := d.strategies[routes.DeliveryPoint]
if isStrategyExists {
resp, err := strategy.Distribute(routes.Deliveries, vehicleNumberPlate, tx)
if err != nil {
tx.Rollback()
logrus.Errorf("Error while distributing: %v", err)
return nil, err
}
routeResponse.DeliveryPoint = routes.DeliveryPoint
routeResponse.Deliveries = *resp
routeList = append(routeList, routeResponse)
} else {
logrus.Errorf("Invalid delivery point: %v", routes.DeliveryPoint)
return nil, errors.New("invalid delivery point")
}
}
response.RouteResponse = routeList
err := d.checkSackPackagesAreUnloaded()
tx.Commit()
if err != nil {
return nil, err
}
return &response, nil
}
以上是你要翻译的内容。
英文:
I'm aiming to do transaction management in the code below. If there is an error in one of the strategies, I am trying to rollback. While testing the code, I noticed that if the rollback or commit command works once, it gives error = transaction has already been committed or rolled back the second time. How can I resolve this error?
func (d *DistributeService) Distribute(vehicleNumberPlate string, request model.DistributeRequest) (*model.DistributeResponse, error) {
var response model.DistributeResponse
response.Vehicle = vehicleNumberPlate
var routeList []model.RouteResponse
tx := d.repo.BeginTransaction()
for _, routes := range request.RouteRequest {
var routeResponse model.RouteResponse
strategy, isStrategyExists := d.strategies[routes.DeliveryPoint]
if isStrategyExists {
resp, err := strategy.Distribute(routes.Deliveries, vehicleNumberPlate, tx)
if err != nil {
tx.Rollback()
logrus.Errorf("Error while distributing: %v", err)
return nil, err
}
routeResponse.DeliveryPoint = routes.DeliveryPoint
routeResponse.Deliveries = *resp
routeList = append(routeList, routeResponse)
} else {
logrus.Errorf("Invalid delivery point: %v", routes.DeliveryPoint)
return nil, errors.New("invalid delivery point")
}
}
response.RouteResponse = routeList
err := d.checkSackPackagesAreUnloaded()
tx.Commit()
if err != nil {
return nil, err
}
return &response, nil
}
答案1
得分: 1
你可能在每次调用中使用相同的事务对象。
如果它被关闭了一次 - 不管出于什么原因 - 你需要创建一个新的事务对象。
你为什么会问我说你可能在使用相同的事务对象呢?
因为你基本上是在传递一个指向 d *DistributeService
的指针。
然后使用 tx := d.repo.BeginTransaction()
。我们无法确定这段代码的具体作用,但我很确定你在这里返回的是相同的事务对象,用于后续的运行。
解决方法是在每次调用该方法时创建一个新的事务对象,例如使用 tx := db.Begin()
,如文档所述。
英文:
You're probably using the same transaction object in each call.
If it was closed once - for whatever reason - you need to create a new transaction object.
Why do I say you are probably using the same transaction object you ask?
Because you're basically passing a pointer to d *DistributeService
.
And then use tx := d.repo.BeginTransaction()
. We can't tell what that code does, but I'm pretty sure you're returning the same transaction object here for subsequent runs.
The solution is to create a new transaction object every time this method is called, f.e. with tx := db.Begin()
as described in the docs.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论