IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Spring Java Discussion :

[SPRING 2.5][JPA][Hibernate] Rollback [Data]


Sujet :

Spring Java

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 51
    Par défaut [SPRING 2.5][JPA][Hibernate] Rollback
    Bonjour,

    J'ai une question concernant l'opération de rollback dans JPA :

    Pour bien expliquer mon interrogation je vais présenter un exemple :

    J'ai une fonction dans la classe service qui persiste 2 objets différentes de 2 classes DAO :

    Action N°1 persister une Personne :
    Action N°2 mettre à jour un article :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    @Service("service")
    @Transactional
    public class ServiceImpl implements IService {
     
    .....
    private void test() {
    ....
    //Action 1 
    Personne p = new Personne("toto",25);
    PersonneService.save(p);
     
    ....
    //Action 2
    Article a = ArticleService.getArticleByName("XXX");
    a.setVendeur(p);
    ArticleService.update(a);
    ....
    }
    Question :

    Comment faire en sorte que si l'action N°2 échoue, faire un rollback pour annuler l'action N°1 ?
    Si j'englobe mon traitement dans un try catch, je remarque que le système sauvegarde quand même la personne même si la mise à jour de l'article échoue !
    Merci de vos réponses.

  2. #2
    Membre expérimenté Avatar de sewatech
    Inscrit en
    Février 2007
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 55

    Informations forums :
    Inscription : Février 2007
    Messages : 141
    Par défaut
    Si ta méthode renvoie une RuntimeException, le TransactionManager déclenchera un rollback sur l'ensemble des requêtes de la méthode.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 51
    Par défaut
    Je pensais la même chose que toi mais à ma grande surprise non. Etant donnée que c'est un appel à 2 méthodes différentes, si la première passe et que la seconde échoue, il ne fait pas un rollback sur la première.

    Je catche l'erreur dans mon traitement mais mais en regardant dans la base, je vois qu'il rajoute quand même la personne mais pas l'article

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    private void test() {
    try{
    ....
    //Action 1 
    Personne p = new Personne("toto",25);
    PersonneService.save(p);
     
    ....
    //Action 2
    Article a = ArticleService.getArticleByName("XXX");
    a.setVendeur(p);
    ArticleService.update(a);
    ....
    } catch (Exception e) {// Catch exception if any
    	System.err.println("Error: " + e.getMessage());
    }
    }

  4. #4
    Membre expérimenté Avatar de sewatech
    Inscrit en
    Février 2007
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 55

    Informations forums :
    Inscription : Février 2007
    Messages : 141
    Par défaut
    C'est ta méthode test qui est transactionnelle, c'est donc à son niveau que sont gérées les transactions. Si tu attrapes l'exception, il y aura commit, alors que si tu laisses monter une RuntimeException, il y aura rollback.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 51
    Par défaut
    Non je viens de tester mais sans succès.
    J'ai enlevé le try catch mais je vois qu'il persiste tout de même la personne !

    La 2 eme solution est que je chose l'exception et que je fasse un delete de la personne ! Mais c'est pas commode chaque fois

  6. #6
    Membre expérimenté Avatar de sewatech
    Inscrit en
    Février 2007
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 55

    Informations forums :
    Inscription : Février 2007
    Messages : 141
    Par défaut
    Je vois que ta méthode est private. Cela signifie donc que tu l'appelles depuis une autre méthode de ServiceImpl. Dans ce cas, c'est elle qui pilotera la transaction (mode Required).

    Essaie de rendre ta méthode test publique et de l'appeler depuis une classe de test indépendante.

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 51
    Par défaut
    regarde ce que j'ai fais :
    J'ai essayé de faire une fonction mais je déclenche une exception à l'intérieur pour voir s'il fait un commit sur la 1ere fonction qui doit fonctionner normalement.
    PS : le champ Name doit être not null

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public class Facade {
       ...
      public void test(Test t) {
    		t.setName("toto");
    		testService.save(t);
    		Test t1 = new Test();
    		testService.save(t1);
    	}
    J'appelle cette fonction depuis mon main :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public static void main(String[] args) throws Exception {
    	// configuration de l'application
    	Injector.init("spring-config.xml");
     
            @Autowired
    	private TestService testService;
            Facade f = new Facade();
            Test t = new Test();
    	f.test(t);
    		...
    }
    s'obtient bien évidemment l'exception mais il a quand même sauvegardé t dans la base sans faire un rolback dessus !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    Exception in thread "main" fr.stime.exception.TechnicalException: javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: fr.stime.entites.Test.name
    	at fr.stime.dao.AbstractDAOBean.save(AbstractDAOBean.java:91)
    	at fr.stime.dao.AbstractDAOBean.save(AbstractDAOBean.java:1)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    	at java.lang.reflect.Method.invoke(Unknown Source)
    	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
    	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:138)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    	at $Proxy31.save(Unknown Source)
    	at fr.stime.service.AbstractServiceBean.save(AbstractServiceBean.java:63)
    	at fr.stime.service.AbstractServiceBean.save(AbstractServiceBean.java:1)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    	at java.lang.reflect.Method.invoke(Unknown Source)
    	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
    	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    	at $Proxy40.save(Unknown Source)
    	at fr.stime.manager.Facade.test(Facade.java:94)
    	at fr.stime.test.InitDB.main(InitDB.java:56)

  8. #8
    Membre expérimenté Avatar de sewatech
    Inscrit en
    Février 2007
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 55

    Informations forums :
    Inscription : Février 2007
    Messages : 141
    Par défaut
    Je commence à ne plus rien comprendre à ton code :
    • Quel rapport entre ce dernier exemple et le premier ?
    • Que fait la déclaration d'un champ private au milieu de ta méthode main ?
    • Comment ta Facade est-elle déclarée dans Spring ?


    Et tant qu'on y est, peux-tu ajouter la déclaration de ton TransactionManager et préciser le type de base de données ?

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 51
    Par défaut
    Je commence à ne plus rien comprendre à ton code :
    Désolé c'est de ma faute. Je n'étais pas très clair. Mais je te rassure ce que tu m'as dit marche parfaitement.

    Mon erreur est que mes opérations de sauvegarde étaient réalisées dans ma classe main et non pas dans ma classe service Ceci explique pourquoi il n'y avait pas de rollback.
    En fait Spring affecte à chaque appel d'une méthode de ma couche service une transaction indépendante. Etant donnée que les traitement n'étaient pas réalisés au sein d'une même fonction, le rollback ne pouvait forcement pas se passer.

    Lorsque je mes les 2 actions dans la même méthode comme tu le m'as dit, un rollback est fait dès que l'une de mes 2 méthodes échoue.

    Merci sewatech pour ton aide.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 09/08/2012, 13h54
  2. JPA/Hibernate/Spring sans Java EE ?
    Par dingoth dans le forum JPA
    Réponses: 10
    Dernier message: 08/09/2011, 11h47
  3. spring test with jpa-mysql-hibernate.
    Par kossistus dans le forum Spring
    Réponses: 1
    Dernier message: 09/05/2008, 00h28
  4. [Data] Spring + JPA (hibernate) + Tomcat
    Par balteo dans le forum Spring
    Réponses: 1
    Dernier message: 19/11/2007, 11h06
  5. [Data] [Spring/Hibernate] RollBack sur plusieurs ajouts
    Par eracius dans le forum Spring
    Réponses: 3
    Dernier message: 31/10/2007, 11h54

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo