Spring Optimistic Locking: Comment réessayer la méthode transactionnelle jusqu'à la validation du commit

J'utilise Spring 2.5 et Hibernate JPA mise en oeuvre avec Java et "conteneur" gérer les Transactions.

J'ai un "après que l'utilisateur est s'engager" la méthode qui met à jour les données en arrière-plan et doivent être engagée indépendamment de ConcurrencyFailureException ou StaleObjectStateException exception, car il ne sera jamais montré au client. En d'autres termes, la nécessité de rendre Optimiste Verrouillage Pessimiste. (Qui pourrait se produire si les méthodes d'exécution est de prendre un peu plus longtemps et quelqu'un a modifié des données dans d'autres transactions)


J'ai lu beaucoup de choses sur la quantité des choses, réessayer exception dans recherche pour DEFAULT_MAX_RETRIES ou 6.2.7. Exemple ou chapitre 14.5. Réessayer. J'ai aussi trouvé dans stackoverflow ici et ici.

J'ai essayé ceci:

public aspect RetryOnConcurrencyExceptionAspect {

    private static final int DEFAULT_MAX_RETRIES = 20;
    private int maxRetries = DEFAULT_MAX_RETRIES;

    Object around(): execution( * * (..) ) && @annotation(RetryOnConcurrencyException) && @annotation(Transactional) {

        int numAttempts = 0;
          RuntimeException failureException = null;
          do {
                numAttempts++;
                try {
                    return proceed(); 
                } 
                catch( OptimisticLockingFailureException ex ) {
                    failureException = ex;
                }
                catch(ConcurrencyFailureException ex) {
                    failureException = ex;
                }
                catch( StaleObjectStateException ex) {
                    failureException = ex;
                }
          } while( numAttempts <= this.maxRetries );
          throw failureException;

    }
}

RetryOnConcurrencyException est mon Annotation pour marquer les méthodes qui doivent être retentée, si une exception atteint son apogée. N'a pas fonctionné... j'ai aussi essayé de plusieurs façons, comme SELECT ... FOR UPDATEEntityManager.lock(...)

Quelle est la meilleure façon d'éviter de données obsolètes, sale lit etc. cette stratégie avec le Printemps? Réessayer?, la synchronisation?, APP lock?, l'isolement?, sélectionner ... pour la mise à jour? Je ne pouvais pas le faire fonctionner et je suis vraiment heureux sur toute aide.


Voici le pseudo-code que j'aime faire:

void doSomething(itemId) {
    select something into A;
    select anotherthing into B;

    //XXX
    item = getItemFormDB( itemId ); //takes long for one user and for other concurrent user it could take less time
    item.setA(A);
    item.setB(B);

    //YYYY
    update item; 
}

Entre //XXX //YYY une autre session peut modifier l'élément, puis le StaleObjectStateException est lancée.

source d'informationauteur knarf1983