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 :

Problème de one-to-many update au lieu de delete insert


Sujet :

Hibernate Java

  1. #1
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2011
    Messages
    196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2011
    Messages : 196
    Par défaut Problème de one-to-many update au lieu de delete insert
    Bonjour bonjour,

    Je vous explique mon problème :

    J'ai deux classes "SUPPORT_RULES" et "MATERIAL_CONFIGURATIONS"

    - Un "SUPPORT_RULES" peut avoir 0-* "MATERIAL_CONFIGURATIONS"

    Ainsi dans ma classe SupportRule j'ai un attribut :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    private Set<MaterialConfiguration> materialConfigurations;
    Ce que je souhaite, c'est faire un delete de tous les éléments de cette liste puis en insérer de nouveaux.

    j'ai donc créé une nouvelle liste intitulée "selectedMaterialConfigurations" dans laquelle j'ai inséré plusieurs "materialConfiguration". Enfin je met à jour la liste materialConfigurations dans mon supportRule.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    supportRule.setMaterialConfigurations (selectedMaterialConfigurations);
    Le problème c'est qu'au lieu de faire un delete et d'insérer les nouvelles "MaterialConfiguration", hibernate fait une requête de type update.

    Quelqu'un a-t-il déjà rencontré ce type de problème ?

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    Si tu veux vraiment supprimer ta collection, tu dois faire un delete explicite sur chaque élément de cette collection, ou passer par une requête.

  3. #3
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    les collection sont surchargées par hibernate pour gérer le tracking des éléments. Donc remplace simplement par ce code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    supportRule.getMaterialConfigurations().removeAll();
    supportRule.getMaterialConfigurations().addAll(selectedMaterialConfigurations);

  4. #4
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2011
    Messages
    196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2011
    Messages : 196
    Par défaut
    Ton idée est judicieuse, j'ai essayé mais malheuresement il fait toujours un update.

    J'ai beaucoup de mal à comprendre car un peu avant je fais exactement la même chose, sauf que c'est pour une relation ManyToMany et dans les requêtes SQL je vois bien qu'Hibernate fait un delete de la collection puis un insert.

    Je pense donc que mon problème peut venir du mapping hibernate que voici :

    SupportRule.hbm.xml

    <hibernate-mapping package="com.genigraph.agir.server.model" default-access="field">
    <class name="SupportRule" table="SUPPORT_RULES">
    <id name="id" column="ID" type="long" unsaved-value="0">
    <generator class="native">
    <param name="sequence">SUPPORT_RULES_SEQ</param>
    </generator>
    </id>

    <property name="label" column="LABEL" type="string"/>
    <property name="name" column="NAME" type="string"/>
    <property name="dayType" column="DAY_TYPE" type="string"/>

    <set name="materialConfigurations" table="MATERIAL_CONFIGURATIONS" lazy="true" inverse="true" cascade="all">
    <key column="SRUL_ID"/>
    <one-to-many class="MaterialConfiguration"/>
    </set>
    </class>
    </hibernate-mapping>
    MaterialConfiguration.hbm.xml

    <hibernate-mapping package="com.genigraph.agir.server.model" default-access="field">
    <class name="MaterialConfiguration" table="MATERIAL_CONFIGURATIONS">

    <composite-id name="id" class="com.genigraph.agir.server.persistence.userTypes.MaterialConfigurationId">
    <key-property name="supportRuleId" column="SRUL_ID" type="long"/>
    <key-property name="equipmentClassId" column="EC1_ID" type="long"/>
    </composite-id>

    <property name="quantityMin" column="QUANTITY_MIN" type="int"/>
    <property name="quantityMax" column="QUANTITY_MAX" type="int"/>

    <many-to-one name="supportRule" class="SupportRule" column="SRUL_ID" insert="false" update="false"/>
    <many-to-one name="equipmentClass" class="EquipmentClass" column="EC1_ID" insert="false" update="false"/>

    </class>
    </hibernate-mapping>

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    Pour un many-to-many c'est normal, c'est une table d'association dont la clef primaire (non modifiable) est composée de clés étrangères, donc on ne peut que supprimer pour recréer.

    Je persiste à dire que si tu veux supprimer ta collection, tu dois passer par un delete explicite.

  6. #6
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2011
    Messages
    196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2011
    Messages : 196
    Par défaut
    En fait ce que je cherche a faire c'est pas directement faire un delete sur ma collection, c'est plutôt la mettre à jour en base de données :

    Imaginons qu'au départ j'ai 3 objets dans ma collection (o1,o2,o3).
    Au sein de ma méthode je modifie ma collection (exemple je supprime o2 et j'ajoute un nouvel objet o4)

    Je pensais qu'hibernate se chargeait de synchroniser lui-même les données en base, sans que j'ai a faire un delete et un insert explicite sur ma collection pour enlever o2 et ajouter o4.

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    Ah ok.
    Ben il faut dans ce cas modifier l'autre côté du lien tonMaterialConfiguration.supportRule(null);

  8. #8
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Ton set est indiqué avec inverse=true. Ca veux dire que ce n'est pas lui qui gère la collection. C'est la relation MaterialConfiguration-> SupportRule qui gère. Donc ce que tu dois faire ce n'est pas ajouter / supprimer dans le set mais appeler les divers MaterialConfiguration.setSupportRule.

  9. #9
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2011
    Messages
    196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2011
    Messages : 196
    Par défaut
    Donc j'ai enlevé le inverse="true" car je veux que ce soit le set qui gère la collection.

    Au final je comprends bien ce qui ne marche pas mais je n'arrive pas à résoudre le problème. En fait tout se passe bien pour l'insertion où la modification d'un MaterialConfiguration dans mon set.

    Le problème vient au niveau de la suppression.
    Je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    supportRule.getMaterialConfigurations ().removeAll()
    et j'obtiens l'erreur suivante : impossible de mettre à jour ("AGIR_PAG"."MATERIAL_CONFIGURATIONS"."SRUL_ID") avec NULL

    J'en déduis que lorsque j'enlève un materialConfiguration dans mon set, il met à jour le champ SRUL_ID dans ma classe MATERIAL_CONFIGURATION pour signifier que le materialConfiguration n'est plus associé avec le supportRule.

    Cela fonctionnerait très bien si le champ SRUL_ID ne faisait pas partie de la clé primaire dans ma classe MATERIAL_CONFIGURATION et comme un champ de la clé primaire ne peut être updater à null j'obtiens l'erreur suivante.

    Du coup je me demande comment résoudre mon erreur...

  10. #10
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    Fais un delete sur ton objet MaterialConfiguration et un remove côté SupportRule.

  11. #11
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    en revoyant ton design, il n'a pas de sens.

    Tu dit que "MATERIAL_CONFIGURATIONS"."SRUL_ID" fait partie de la clé primaire, alors ce champ ne peux jamais être modifié (on ne change pas une clé primiare après stockage de la données). Si tu veux pouvoir dissocier une matérialconfiguration d'une support rule, la support rule ne doit pas faire partie de la clé primaire.

    Aussi, comme tu as une relation bidirectionnelle (supportrule <->materialconfiguration), un des deux cotés doit être marqué comme inverse=true pour hibernate.

  12. #12
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2011
    Messages
    196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2011
    Messages : 196
    Par défaut
    fr1man => J'avais pensé à la même solution que toi, sauf qu'il me met la même erreur. Il fait l'update avant le delete. J'ai donc essayé de faire un delete sans faire de remove côté SupportRule mais j'obtiens l'erreur suivante :
    deleted object would be re-saved by cascade (remove deleted object from associations) ce qui est logique car j'ai un cascade="all" sur mon set mais je ne veux pas l'enlever car lorsque j'ajoute un materialConfiguration dans mon Set je veux qu'il soit persister en base.

    tchize_ => En fait un materialConfiguration n'a pas lieu d'exister s'il n'est pas associé à un supportRule, c'est pour cela que l'id fait partie de la clé primaire. (le schémas est bon, ce n'est pas moi qui l'ai fait). En fait je ne cherche pas à dissocier un materialConfiguration d'un supportRule. Du coup lorsque j'enleve un materialConfiguration du set du supportRule, je veux que le materialConfiguration soit supprimé et non pas que son champ SRUL_ID soit à null ce qui serait incorrect.

  13. #13
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Retire le de la clé primaire (pour permettre le null) et rajoute dans ton set

    cascade="all-delete-orphan"

    Pour empêcher les material configuration orphelins.

  14. #14
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2011
    Messages
    196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2011
    Messages : 196
    Par défaut
    Effectivement avec ta solution cela fonctionnerait.
    Le problème c'est que je ne peut pas le retirer de ma clé primaire, sinon mon mapping hibernate n'est pas en adéquation avec la base de données. Et en base le champ SRUL_ID fait forcément partie de la clé primaire.

    Je voulais donc savoir s'il était possible de modifier le comportement d'hibernate, c'est à dire de supprimer l'enregistrement au lieu de mettre le champ à null au moment où j'enlève un élément dans mon Set.

  15. #15
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    garde le set en inverse=true et fait un delete de l'objet concerné alors, tout simplement

    Si tu veux que ce soit effacé, soit clair avec hibernate, efface.

  16. #16
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2011
    Messages
    196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2011
    Messages : 196
    Par défaut
    Je veux pas mettre le inverse="true" car lorsque j'insère un MaterialConfiguration dans mon Set je veux qu'il soit persister, si je met le inverse="true" ça ne sera plus le cas...

  17. #17
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    ton design est complètement différent. Tu nous dit depuis le début que la clé étrangère fait partie de la clé primaire, donc que material configuration ne peux pas exister sans un support rule.

    Donc, en tout logique ça veux dire que ton code respecte ça et fait bien appel à

    materialConfiguration.setSupportRule(), donc materialConfiguration est correct, donc quand tu le sauvera la relation sera sauvée.

    Pour ton set, le fait qu'il soit en inverse=true ne concerne que la gestion de la clé étrangère. Ca ne veux pas dire que le set ne respecte pas les règle de cascade que tu lui impose éventuellement (insert, merge ou autre).

  18. #18
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2011
    Messages
    196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2011
    Messages : 196
    Par défaut
    le soucis que j'ai, c'est que quand je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    materialConfiguration.setSupportRule(supportRule)
    la relation n'est pas insérée en base et je n'ai aucun message d'erreur. Je ne vois pas ce qui va pas car j'ai bien mis le inverse="true".

  19. #19
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    vous l'avez bien aussi ajouté dans le set? Vous faites comment pour sauver? on peux voir le code complet?

  20. #20
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2011
    Messages
    196
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2011
    Messages : 196
    Par défaut
    Oui, oui bien sûr voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     
    Set<MaterialConfiguration> selectedMaterialConfigurations = new HashSet<MaterialConfiguration> ();
    	for(IdentifiedArray identifiedArray:materialConfigurations)
    	{
    	    EquipmentClass equipmentClass = EquipmentClass.getEquipmentClass (identifiedArray.getString (MaterialConfigurationsFormDTOMapper.LABEL_COLUMN));
    	    MaterialConfiguration materialConfiguration = new MaterialConfiguration ();
    	    materialConfiguration.setSupportRule (supportRule);
    	    materialConfiguration.setEquipmentClass (equipmentClass);
    	    selectedMaterialConfigurations.add(materialConfiguration);
    	}
    	supportRule.setMaterialConfigurations (selectedMaterialConfigurations);

Discussions similaires

  1. Problème hibernate one-to-many / many-to-one
    Par valkeke dans le forum Hibernate
    Réponses: 4
    Dernier message: 02/04/2014, 14h06
  2. [NHibernate] problème de relation one-to-many
    Par Spikuria dans le forum NHibernate
    Réponses: 1
    Dernier message: 30/04/2009, 14h22
  3. Problème de delete sur one-to-many avec une cascade
    Par Theoden dans le forum Hibernate
    Réponses: 2
    Dernier message: 02/01/2009, 17h43
  4. Problème avec <one-to-many>
    Par SyLvErStOrM dans le forum Hibernate
    Réponses: 7
    Dernier message: 09/09/2008, 10h02
  5. Hibernate3 : Problème d'insert avec one-to-many
    Par myocean dans le forum Hibernate
    Réponses: 2
    Dernier message: 22/02/2008, 10h04

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