2
votes

Spring Boot + JPA: annotation @Transactional: la restauration ne fonctionne pas

J'utilise @Transactional avec spring boot et jpa. Mais ça ne fonctionne pas. Quelqu'un peut-il aider.

Mes inserts sont dans myDAO qui est câblé automatiquement en classe de service. Le code ci-dessous est la méthode de la classe de service qui implémente l'interface de service

class MyService implements Service {

@Transactional(rollbackFor = RuntimeException.class)
    public ResponseVO createOrder(params) {
    myDAO.insertInTable1(param);
    myDAO.insertInTable2(param);//I kept wrong table name in this query such that it throws exception
         }

 }


9 commentaires

rien ne va pas ici, donnez comme plus d'infos :)


Votre restauration est uniquement pour RuntimeException , et une mauvaise table ne crée pas une RuntimeException . Lisez le manuel @Transactional .


@Zorglube, j'ai essayé de créer une nouvelle exception d'exécution avec new. Même si aucun retour en arrière.


Il semble que vous ne comprenez pas ce que vous faites, vous n'avez pas besoin de forger une exception vous-même, vous devez choisir le type d'exception que vous annulez ou non.


D'où est appelée la méthode createOrder?


createOrder est appelé depuis la classe de contrôleur


Afficher l'implémentation de MyDao , quelle base de données utilisez-vous également? Si vous utilisez MySQL, assurez-vous que vous utilisez un magasin de tables qui prend en charge les transactions.


J'utilise MYSql, avec le moteur MyISAM. dans DAO, j'insère simplement des données dans table1 et table 2 en utilisant les méthodes JPA save et saveall. (JPARepository)


Si vous souhaitez annuler une transaction sur une exception, la méthode doit lancer une exception ... Vous n'en lancez pas une ici ... ajoutez public ResponseVO createOrder (params) throws Exception { ...}


5 Réponses :


0
votes

C'est difficile à dire à partir de la quantité de code donnée. Je sais que vous ne devriez pas avoir besoin du rollbackFor s'il s'agit de RuntimeException . Ceux-ci sont toujours annulés. Je suppose que l'erreur de nom de votre table est une SQLException qui implémente Exception . Vous devriez avoir rollbackFor être rollbackFor = SQLException.class , et je ne garderais cela que pour vérifier que les annulations se produisent. Ajoutez uniquement le rollbackFor si vous lancez des exceptions vérifiées dans les méthodes appelées par le service.


2 commentaires

J'ai essayé ça aussi. Mais inutile. Mais généralement, les exceptions d'exécution gèrent tous les types d'exceptions. Il devrait donc également attraper cette exception et revenir en arrière.


SQLException est une sous-classe d'Exception et non de RuntimeException. RuntimeException est une sous-classe d'Exception. Seules les sous-classes de RuntimeException seraient annulées.



1
votes

Essayez ceci:

@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = RuntimeException.class)

J'espère que cela vous aidera.

Bravo !!


2 commentaires

J'essaierais également Exception.class dans la restauration.


Le problème était simple bro .. il n'avait pas de clause throws ;) public ResponseVO createOrder (params) {}



-1
votes

Dans Spring Boot, OpenSessionInView est activé par défaut, donc votre restauration ne fonctionne pas car chaque fois que vous appelez myDAO.insertInTableX () , une validation est effectuée.

Donc, pour supprimer ce comportement et que votre @Transactional fonctionne correctement, ajoutez ceci:

spring.jpa.open-in-view=false

À votre application.properties

Voir cette question pour en savoir plus


0 commentaires

2
votes

RuntimeException sont déjà gérés

remplacer par @Transactional (rollbackFor = Exception.class) pour gérer toutes les exceptions cochées et fonctionnera


0 commentaires

4
votes

Le problème vient du moteur de base de données MySQL. Mon moteur était MYIsam qui ne prend pas en charge les transactions. J'ai changé mon moteur DB en InnoDB et son fonctionnement. Merci pour les contributions. Voici les requêtes pour la même chose.

CHOISIR LE MOTEUR FROM information_schema.TABLES OÙ TABLE_NAME = 'nom_table' AND TABLE_SCHEMA = 'nom_base';

ALTER TABLE nom_table ENGINE = INNODB;


1 commentaires

Pour passer à INNODB en utilisant le dialecte de mise en veille prolongée, reportez-vous à stackoverflow.com/questions/1459265/...