Gestion avancée des transactions Spring : attributs rollbackFor et propagation

Après avoir introduit l'annotation @Transactional pour contrôler les transactions, examinons deux attributs essentiels :

  • rollbackFor : Définit les types d'exception déclanchant un rollback
  • propagation : Contrôle le comportement de propagation des transactions
1.3.1 rollbackFor

Par défaut, Spring ne rollback que pour les RuntimeException. Observons ce comportement :

@Transactional
public void supprimerEntite(Integer identifiant) {
    // Suppression de l'entité principale
    entiteRepo.effacer(identifiant);
    
    // Simulation d'exception
    int calcul = identifiant / 0;
    
    // Nettoyage des dépendances
    dependanceRepo.supprimerParEntite(identifiant);
}

L'exception arithmétique provoque un rollback. Mais avec une exception vérifiée :

@Transactional
public void supprimerEntite(Integer identifiant) throws Exception {
    entiteRepo.effacer(identifiant);
    
    if(true) {
        throw new Exception("Erreur critique");
    }
    
    dependanceRepo.supprimerParEntite(identifiant);
}

Contrairement aux attentes, la transaction est validée malgré l'exception. Solution :

@Transactional(rollbackFor = Exception.class)
public void supprimerEntite(Integer identifiant) {
    entiteRepo.effacer(identifiant);
    int test = identifiant / 0; // Exception runtime
    dependanceRepo.supprimerParEntite(identifiant);
}

Cette configuration assure le rollback pour toutes les exceptions.

1.3.3 propagation

Définit comment les transactions interagissent entre méthodes transactionnelles.

Valeur Comportement
REQUIRED (défaut) Rejoint une transaction existante ou en crée une nuovelle
REQUIRES_NEW Crée toujours une nouvelle transaction
SUPPORTS Rejoint une transaction si elle existe
NOT_SUPPORTED Exécute hors transaction
1.3.3.2 Étude de cas

Requête : Journaliser les suppressions de département même en cas d'échec.

@Transactional(rollbackFor = Exception.class)
public void dissoudreDepartement(Integer id) {
    try {
        departementRepo.supprimer(id);
        if(true) throw new Exception("Erreur");
        employeRepo.supprimerParDepartement(id);
    } finally {
        Journal journal = new Journal(
            LocalDateTime.now(), 
            "Suppression département: " + id
        );
        journalService.enregistrer(journal);
    }
}

@Service
public class JournalServiceImpl implements JournalService {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void enregistrer(Journal entree) {
        journalRepo.inserer(entree);
    }
}

Avec REQUIRES_NEW, l'entrée de journal est persistée même si la transaction principale échoue.

Cas d'usage :

  • REQUIRED : Comportement transactionnel standard
  • REQUIRES_NEW : Opérations critiques nécessitant une persistance garantie

Étiquettes: Spring Framework Transactions Java rollbackFor Propagation Annotation Transactional

Publié le 14 juin à 23h37