Spring Boot : écrire le serveur (école d'ingénieur) · Chapitre 6 · Application directe du cours
Deux modifications concurrentes
Relations et transactions · niveau 3 (difficile)
Énoncé
Un administrateur charge la fiche d'un livre (12 en stock), puis, pendant qu'il la modifie, un client commande un exemplaire. L'administrateur enregistre alors sa fiche, avec un stock calculé sur l'ancienne valeur. Quelle est la conséquence ? Ajouter un champ @Version à l'entité Livre et décrire ce qui se passe alors.
Corrigé
Sans précaution, la dernière écriture gagne : l'administrateur réécrit le stock à 12, et la vente du client est effacée, sans erreur (une « mise à jour perdue »). Avec un numéro de version :
@Version
private long version;
Hibernate incrémente la version à chaque mise à jour, et ajoute and version=? au where de chaque update. L'enregistrement de la fiche périmée (version 0) ne touche plus aucune ligne, puisque la base est en version 1 ; Hibernate le détecte, et Spring lève :
Row was already updated or deleted by another transaction for entity [fr.librairie.Livre with id '9782956300014']
une ObjectOptimisticLockingFailureException, que l'API peut traduire en 409 Conflict. C'est le verrouillage optimiste : on ne bloque personne, on détecte le conflit à l'écriture.
void ex9_verrouOptimiste() {
Livre copiePerimee = livres.findById(JAVA).orElseThrow(); // version 0, détachée
service.commander(demande("a@x.fr", new LigneDemande(JAVA, 1))); // base : version 1
copiePerimee.retirerDuStock(2);
assertThatThrownBy(() -> livres.save(copiePerimee))
.isInstanceOf(ObjectOptimisticLockingFailureException.class)
.satisfies(e -> System.out.println("ex9 : " + e.getMessage()));
assertThat(livres.findById(JAVA).orElseThrow().getStock()).isEqualTo(11);
}100 % gratuit
La suite du chapitre est sur Adloun
- 9 autres exercices corrigés dans ce chapitre
- Les 2 QCM du chapitre, le premier sans compte
- Le tuteur, qui guide pas à pas sans donner la réponse
Sans compte : le cours et le premier QCM. Exercices et tuteur : inscription gratuite en 30 secondes, sans carte bancaire.