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

Hibernate Java Discussion :

cascade = {CascadeType.REMOVE} pas suffisant?


Sujet :

Hibernate Java

  1. #1
    Membre habitué
    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2008
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 39
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 379
    Points : 129
    Points
    129
    Par défaut cascade = {CascadeType.REMOVE} pas suffisant?
    Bonjour,

    J'ai deux entités : Membre et Questionnaire qui sont en association ManyToMany avec une colonne supplémentaire. J'ai donc aussi une entité ListeQuestionnaire qui représente l'association et une classe ListeQuestionnairePk pour la clé composite.

    dans mon entité Questionnaire, j'ai donc une association @OneToMany avec ListeQuestionnaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    	@OneToMany(mappedBy = "pk.questionnaire", cascade = {CascadeType.REMOVE}, fetch = FetchType.LAZY)
    	private List<ListeQuestionnaire> listeQuestionnaires = new ArrayList<ListeQuestionnaire>();
    C'est dans ma classe métier ServiceQuestionnaire que je remplis la table ListeQuestionnaire par la méthode publierQuestionnaire :
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    @Transactional
    public Questionnaire publierQuestionnaire(Long idQuestionnaire){
    	System.out.println("------------ publierQuestionnaire");
    	Questionnaire questionnaire = questionnaireDao.getOne(idQuestionnaire);
    	Character sexeDestinataire = questionnaire.getSexeDestinataire();
     
    	if(sexeDestinataire != null)
    	{	
    		//On recherche tous les membres concernés par ce questionnaire
    		List<Membre> membreConcernes = null;
    		switch(sexeDestinataire)
    		{
    			case 'f' :
    			{
    				membreConcernes = serviceMembre.findFemmes();
    				break;
    			}
    			case 'h' : 
    			{
    				membreConcernes = serviceMembre.findHommes();
    				break;
    			}
    			case 'b' :
    			{
    				membreConcernes = serviceMembre.findAll();
    				break;
    			}
    		}
     
    		//On enregistre les liens entre le nouveau questionnaire et les membres concernés
    		for (Membre membre : membreConcernes) {
    			ListeQuestionnaire listeQ = new ListeQuestionnaire();
    			listeQ.setARepondu(false);
    			listeQ.setMembre(membre);
    			listeQ.setQuestionnaire(questionnaire);
    			listeQ = serviceListeQuestionnaire.saveOne(listeQ);
    			questionnaire.getListeQuestionnaires().add(listeQ);
    		}
     
    		questionnaire.setPublie(true);
    		questionnaire = questionnaireDao.saveOne(questionnaire);
    	}
    	else
    	{
    		throw new RuntimeException("Le sexe des destinataires du questionnaire n'est pas défini !");
    	}
     
    	return questionnaire;
    }
    quand les lignes 40-41 sont commentées, la méthode fonctionne bien.
    Par contre, quand ces lignes sont présentes, je me retrouve avec l'erreur suivante, lancée par questionnaire = questionnaireDao.saveOne(questionnaire);:
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    javax.persistence.EntityNotFoundException: Unable to find fr.statlife.protoE4N.data.entites.ListeQuestionnaire with id ListeQuestionnairePk [idMembre=ben.joris, idQuestionnaire=1]
    	at org.hibernate.ejb.Ejb3Configuration$Ejb3EntityNotFoundDelegate.handleEntityNotFound(Ejb3Configuration.java:132)
    	at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:233)
    	at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:285)
    	at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152)
    	at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1080)
    	at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:1028)
    	at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:623)
    	at org.hibernate.type.EntityType.resolve(EntityType.java:431)
    	at org.hibernate.type.EntityType.replace(EntityType.java:291)
    	at org.hibernate.type.CollectionType.replaceElements(CollectionType.java:507)
    	at org.hibernate.type.CollectionType.replace(CollectionType.java:574)
    	at org.hibernate.type.TypeFactory.replace(TypeFactory.java:548)
    	at org.hibernate.event.def.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:563)
    	at org.hibernate.event.def.DefaultMergeEventListener.entityIsPersistent(DefaultMergeEventListener.java:288)
    	at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:261)
    	at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:84)
    	at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:859)
    	at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:843)
    	at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:847)
    	at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:682)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:597)
    	at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
    	at $Proxy30.merge(Unknown Source)
    	at fr.statlife.protoE4N.data.dao.jpa.AbstractDaoJPAImpl.saveOne(AbstractDaoJPAImpl.java:44)
    	at fr.statlife.protoE4N.metier.ServiceQuestionnaireImpl.publierQuestionnaire(ServiceQuestionnaireImpl.java:96)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:597)
    	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
    	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    	at $Proxy38.publierQuestionnaire(Unknown Source)
    	at fr.statlife.protoE4N.metier.TestServiceQuestionnaire.testPublierQuestionnaireHomme(TestServiceQuestionnaire.java:79)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:597)
    	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
    	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
    	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
    	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    	at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
    	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
    	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
    Il me dit qu'il trouve pas une entité ListeQuestionnaire, j'en déduis qu'il cherche à enregistrer le champs List<ListeQuestionnaire> listeQuestionnaires du questionnaire.
    Pourtant, je pensais que spécifier cascade = {CascadeType.REMOVE} de l'annotation @OneToMany était suffisant pour qu'il fasse abstraction de ce champs

    Du coup je comprends pas trop où est mon erreur. Est ce que quelqu'un pourrait éclairer ma lanterne sur ce qu'il se passe ?

  2. #2
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2011
    Messages : 214
    Points : 338
    Points
    338
    Par défaut
    Bonjour,

    Citation Envoyé par zaboug Voir le message
    je me retrouve avec l'erreur suivante, lancée par questionnaire = questionnaireDao.saveOne(questionnaire);
    Pourquoi faire un merge du questionnaire alors qu'apriori il est déjà managé puisque récupéré via un DAO à la ligne 4 ?

  3. #3
    Membre habitué
    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2008
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 39
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 379
    Points : 129
    Points
    129
    Par défaut
    erreur de débutant
    en fait, au départ j'en avais pas fait, mais ça me génèrait une autre erreur :
    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
    Hibernate: 
        update
            Questionnaire 
        set
            numero=?,
            publie=?,
            sexeDestinataire=?,
            titre=? 
        where
            idQuestionnaire=?
    WARN  - JDBCExceptionReporter      - SQL Error: 1205, SQLState: 41000
    ERROR - JDBCExceptionReporter      - Lock wait timeout exceeded; try restarting transaction
    ERROR - tractFlushingEventListener - Could not synchronize database state with session
    org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
    [...]
    et j'ai fini par perdre de vue cette première erreur

    au final, il suffit d'ajouter l'attribut propagation à l'annotation @Transactional de la méthode pour que ça passe bien (après avoir supprimé l'appel au merge, biensur):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @Transactional(propagation=Propagation.NEVER)
    Par contre je ne maitrise pas bien cette annotation, pourquoi elle est nécessaire ici mais pas toute les méthodes?
    Faut-il la mettre en prévention partout pour être sur ?
    J4ai du mal à mesurer son impact...

  4. #4
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2011
    Messages : 214
    Points : 338
    Points
    338
    Par défaut
    Ta première erreur c'était apparemment un timeout sur un lock.

    Mais là je ne suis pas sûr que ça soit vraiment ça que tu veuilles faire. Avec Propagation.NEVER tu demandes l'exécution hors transaction (et même de lever une exception si une transaction est en cours)...

  5. #5
    Membre habitué
    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2008
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 39
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 379
    Points : 129
    Points
    129
    Par défaut
    arf
    bon, alors ça résoud le problème sans être la solution...
    en fait, j'avais trouvé cette solution sur le forum stackoverflow quand j'avais eu la même erreur dans ma classe de tests unitaire du dao de ListeQuestionnaire.
    sur ce forum il est dit
    You can solve it by breaking main transaction into several separate transactions
    le problème était pas exactement le même, mais l'erreur si, donc j'en avais déduis que l'attribut propagation.NEVER permettait de lancer plusieurs transaction à la suite plutôt qu'une grosse transaction rassemblant le tout...

    tu as une autre idée de la source possible d'un timeout de la requête lors d'un update? parce que je sais pas du tout dans quelle direction aller chercher du coup

  6. #6
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2011
    Messages : 214
    Points : 338
    Points
    338
    Par défaut
    Tu n'es pas la première a avoir ce genre de soucis dernièrement.

  7. #7
    Membre habitué
    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2008
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 39
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 379
    Points : 129
    Points
    129
    Par défaut
    ouahou !
    merci pour le lien, j'ai lu la discussion dans son ensemble et le niveau est largement supérieur au mien !

    Bon, moi aussi j'utilise MySQL... est ce que je dois en déduire qu'il faut que je passe sous oracle pour que ça marche ??

    toutes les méthodes de mes services sont annotées avec @Transactional tout seul (donc REQUIRED par défaut il me semble). Les méthodes de mes Dao ne sont pas annotés car elles ne sont appelées que par mes services ou par les tests unitaires qui sont elles aussi annotées par @Transactional (est ce une mauvaise pratique).

    les méthodes de test des services et les tests d'acceptation qui inclue l'IHM (tests d'intégration) ne sont pas annotés par transactional.

  8. #8
    Membre averti
    Homme Profil pro
    Inscrit en
    Avril 2011
    Messages
    214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2011
    Messages : 214
    Points : 338
    Points
    338
    Par défaut
    Il n'y a rien qui me choque en ce qui concerne tes transactions mais je ne connais pas toute ton appli.
    Si tu as des méthodes de tes services qui ne font pas de mofication des objets persistés tu peux utiliser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @Transactional(readOnly=true)
    pour essayer d'optimiser. Ça peut aussi jouer sur le problèmes de locks mais c'est sans garantie.

    Si t'as l'occasion de tester avec un autre SGBD (pas forcément Oracle) ça peut être intéressant sinon je pense (mais je peux me tromper) que ça reste spécifique à MySql: quelque chose de non supporté ou à reconfigurer (mais ça me dépasse aussi).

  9. #9
    Membre habitué
    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2008
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 39
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 379
    Points : 129
    Points
    129
    Par défaut
    en fait, pour l'instant il n'y a que les méthodes de service qui jouent avec l'entité ListeQuestionnaires qui ont se problème de Lock... y'a aucun souci pour les autres. Mais faut dire que j'en suis au début du développement de l'appli...

    Du coup, pour aujourd'hui je laisse les propagation en NEVER pour les 2-3 méthodes qui bloquent et j'essaierai avec un autre SGBD à mon retour de vacances

    merci pour tout, on peut considérer le sujet comme résolu

  10. #10
    Membre habitué
    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2008
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 39
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 379
    Points : 129
    Points
    129
    Par défaut
    J'ai remplacé MySQL par PostgreSQL, plus de problème de lock, mais apparition de problème de clé étrangère visiblement...
    J'ai créé une nouvelle discussion à ce sujet car encore une fois je m'en sors pas

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 27/08/2009, 03h31
  2. [Tableaux] array_unique() pas suffisant
    Par Anduriel dans le forum Langage
    Réponses: 3
    Dernier message: 25/08/2009, 12h34
  3. out of memory java heap space : 2048M pas suffisant?
    Par waflyx dans le forum Eclipse Java
    Réponses: 5
    Dernier message: 21/12/2007, 19h58
  4. Clé étrangère et CASCADE ne fonctionne pas (MySQL 5.0)
    Par ctobini dans le forum Administration
    Réponses: 3
    Dernier message: 07/11/2007, 15h44
  5. Cascade="all" ou pas ?
    Par gazier20 dans le forum Hibernate
    Réponses: 2
    Dernier message: 16/06/2007, 15h55

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