Maison >développement back-end >Golang >Erreur d'erreur de transaction Gorm = transaction validée ou annulée

Erreur d'erreur de transaction Gorm = transaction validée ou annulée

WBOY
WBOYavant
2024-02-10 23:09:07639parcourir

Gorm 事务错误 error = 事务已提交或回滚

l'éditeur php Youzi vous présentera un message d'erreur courant dans cet article : "Erreur de transaction Gorm = transaction a été validée ou annulée". Lorsque vous utilisez Gorm pour des opérations de base de données, vous rencontrez parfois cette erreur, qui prête à confusion. Cet article expliquera en détail la cause de cette erreur et les solutions possibles pour aider les lecteurs à résoudre ce problème et à effectuer les opérations de base de données en douceur.

Contenu de la question

Mon objectif est de faire la gestion des transactions dans le code ci-dessous. Si quelque chose ne va pas avec l’une des stratégies, j’essaie de revenir en arrière. En testant le code, j'ai remarqué que si la commande rollback ou commit est exécutée une fois, elle donne l'erreur = la transaction a été validée ou annulée une seconde fois. Comment corriger cette erreur ?

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
}

Solution de contournement

Vous utilisez peut-être le même objet de transaction à chaque appel. S'il est fermé une fois - pour une raison quelconque - vous devez créer un nouvel objet de transaction.

Pourquoi ai-je dit que vous utilisiez probablement le même objet de transaction que celui que vous avez demandé ? Parce que vous passez essentiellement un pointeur vers d *DistributeService. Alors utilisez tx := d.repo.BeginTransaction(). Nous ne pouvons pas dire ce que fait ce code, mais je suis presque sûr que vous renvoyez ici le même objet de transaction pour les exécutions ultérieures.

La solution est de créer un nouvel objet de transaction à chaque fois que cette méthode est appelée, par exemple en utilisant tx := db.Begin() comme décrit dans la documentation.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer