Je me demande s'il est logique d'utiliser au lieu de
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
utiliser Throwable
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
Si je comprends bien, la capture de Error
nous aidera à nous comporter correctement même en cas de problème grave. Ou peut-être que cela n'aiderait pas?
Si je comprends bien, la capture d'une erreur nous aidera à nous comporter correctement même en cas de problème grave. Ou peut-être que cela n'aiderait pas?
Vous n'avez pas besoin de spécifier explicitement rollbackFor = Throwable.class
, car le printemps annulera par défaut la transaction si un Error
se produit.
Voir 12.5.3 Annulation d'une transaction déclarative
Dans sa configuration par défaut, le code d'infrastructure de transaction de Spring Framework ne marque une transaction pour restauration que dans le cas d'exceptions non vérifiées au moment de l'exécution; c'est-à-dire lorsque l'exception levée est une instance ou une sous-classe de RuntimeException. (Les erreurs entraîneront également - par défaut - un retour en arrière) . Les exceptions vérifiées qui sont levées à partir d'une méthode transactionnelle n'entraînent pas de restauration dans la configuration par défaut.
Ou jetez un œil à DefaultTransactionAttribute
public boolean rollbackOn(Throwable ex) {
return (ex instanceof RuntimeException || ex instanceof Error);
}
Puisque vous utilisez @Transactional
, nous pouvons supposer en toute sécurité que vous effectuez vos opérations de base de données via Spring, Hibernate ou d'autres wrappers JDBC. Ces wrappers JDBC ne génèrent généralement pas d'exceptions vérifiées, ils génèrent des exceptions d'exécution qui encapsulent les types JDBC SQLException
.
@Transactional
est configuré pour restaurer, par défaut, uniquement lorsqu'une exception non vérifiée est levée.
Considérons un cas d'utilisation comme celui-ci
@Transactional
public void persistAndWrite(Bean someBean) throws IOException {
// DB operation
getSession().save(someBean);
// File IO operation which throws IOException
someFileService.writeToFile(someBean);
}
Vous ne voudriez pas nécessairement annuler l'opération DB simplement parce que nous n'avons pas pu écrire quelque chose dans un fichier.
De même
@Transactional
public void persistAndThrowOutOfMemory(Bean someBean) {
// DB operation
getSession().save(someBean);
// consumes all memory, throws OutOfMemoryError
someService.hugeOperationThrowsOutOfMemoryError();
}
Vous ne voudriez pas nécessairement annuler l'entité enregistrée simplement parce que certains services entraînent une consommation excessive de mémoire.
@Transactional
vous donne l'option. Utilisez-le le cas échéant.
La valeur par défaut de la restauration est l'enregistrement sur l'exception d'erreur, mais lorsque vous vous inscrivez try{}catch{}
manuellement, il remplace l'erreur, donc dans ce cas, utilisez
catch {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
pour le faire manuellement ou supprimer try catch
vous pouvez également enregistrer le type d'exception dans les annotations transactionnelles telles que:
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
Je ne sais pas si c'est possible ou pas mais la manipulation de Throwable
s comme Error
s est un mauvais style de programmation, ce n'est pas la responsabilité des développeurs de gérer ce genre d'erreurs fatales. Il peut toujours arriver de mauvaises choses que vous ne pouvez pas gérer. Vous devez gérer les exceptions vérifiées si nécessaire, qui sont connues de votre système comme un certain type d'erreurs logiques.