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

Java Discussion :

Référence non unique après désérialisation


Sujet :

Java

  1. #1
    Membre régulier Avatar de damtoul
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juillet 2015
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juillet 2015
    Messages : 60
    Points : 104
    Points
    104
    Par défaut Référence non unique après désérialisation
    Bonjour,

    J'ai un problème de référence entre objets que je n'arrive à résoudre. Mon problème vient de la sérialisation/désérialisation des données car quand le programme tourne, lorsque je fais des modifications sur les instances, tout est bien mis à jour.
    Pour résumer rapidement j'ai une liste de produits de base, qui rentrent dans la composition d'un produit fini. Lorsque je modifie un produit de base, les mêmes produits de base qui composent un produit fini sont bien mis à jour puisqu'ils ont la même référence.
    Lorsque je relance le programme et que je désérialise mes données pour récupérer mes instances de produits de base et de produits finis, forcément mes produits de base qui composent mes produits finis n'ont plus la même référence que mes produits de base car ils sont sauvés dans des fichiers différents.

    J'ai donc mis en place une fonction pour updater les références mais ça ne marche pas et je comprends pas. L'algorithme semble bon puisque la console m'affiche bien le message d'update mais l'instruction ne semble pas avoir d'effet car quand je fais un affichage des instances de produits de base et des produits de base d'un produit fini l'update n'a clairement pasd fonctionné.

    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
    public void syncBaseProductsAtLoading(TreeSet<BaseProduct> bpset)
       { 
    	/** Iterate the finished product map for each entry<K,V> **/
        for ( Entry<ProductFamily,TreeSet<FinishedProduct>> entry : this.menumap.entrySet() )
    	 {
    	  /** For each finished product in the menumap, update the reference of their base products **/
    	  for ( FinishedProduct fp : entry.getValue() )
      	   {
    		Iterator<BaseProduct> iter=fp.getBaseProductList().iterator();
    		while ( iter.hasNext() )
    		 {
    		  BaseProduct bp=iter.next();
    		  for ( BaseProduct bpref : bpset )
    		   {
    			if ( bpref.getName().equals(bp.getName()) )
    			  {
    			   System.out.println("Produit de base "+bp.getName()+bp+" remplacé par "+bpref.getName()+bpref);
    			   bp=bpref;
    			  }
    		   }
    		 }
      	   }
         }
       }
    Je suis preneur d'une solution pour ce cas, où d'une autre solution plus légère/optimisée que je pourrais mettre en place car je trouve cette fonction d'update un peu lourde. De plus je ne comprends PAS DU TOUT pourquoi l'affectation d'instance ne marche pas....

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Hello,

    Je ne comprends pas très bien comment tu as réussi à avoir un problème, mais a priori il suffit de définir la liste des produits de base, avec un nom unique, d'une part, puis d'enregistrer un produit fini sous forme de liste de noms de produits de base, d'autre part.

    Comme à la désérialisation, tu n'as alors qu'une liste de noms au lieu d'une liste de produits, il suffit de transformer chaque nom en produit, en allant consulter la liste des produits existants avec leur nom. Et du coup, chaque référence de produit de base, reste unique : la référence étant celle qui a été définie par la liste de produits existants.

    Citation Envoyé par damtoul Voir le message
    De plus je ne comprends PAS DU TOUT pourquoi l'affectation d'instance ne marche pas....
    Ta ligne, c'est :

    Et si je te montre le code suivant :

    Est-ce que tu saisis mieux pourquoi ta ligne ne peut pas avoir d'effet, ou est-ce que tu estimes que mon bout de code demande à modifier les mathématiques pour que le nombre 4 devienne en fait le nombre 2 ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre régulier Avatar de damtoul
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juillet 2015
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juillet 2015
    Messages : 60
    Points : 104
    Points
    104
    Par défaut
    Bonjour Thelvin,

    Merci pour ta réponse.

    Je vais effectivement voir si à la sérialisation je peux raccrocher tout ça.

    Pour le problème de référence c'est tout con j'ai compris pourquoi mon bp=bpref ne marchait pas, et ça n'a pas à voir avec ton explication : l'affectation se déroule bien, mais évidemment uniquement DANS la fonction.

    Je vais donc retourner ma hashmap à la fin de ma fonction et tout devrait être ok. Au moins ça va marcher et ça va me permettre de réfléchir à tête reposé à une meilleure implémentation car je trouve ça lourdaud : ça va avec quelques produits mais quand il y en aura beaucoup ça risque de pédaler un peu....

    Dam.

  4. #4
    Membre régulier Avatar de damtoul
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juillet 2015
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juillet 2015
    Messages : 60
    Points : 104
    Points
    104
    Par défaut
    Edit rapide : bon bah ça veut pas.

    Sur ce dernier bout de code j'ai ajouté deux affichages et les deux instances ont bien la même référence.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    			if ( bpref.getName().equals(bp.getName()) )
    			  {
    			   System.out.println("Produit de base "+bp.getName()+bp+" remplacé par "+bpref.getName()+bpref);
    			   bp=bpref;
    			   System.out.println("bpref"+bpref);
    			   System.out.println("bp"+bp);
    			  }
    Toujours dans la fonction je relance une itération pour réafficher tout :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        for ( Entry<ProductFamily,TreeSet<FinishedProduct>> entry : this.menumap.entrySet() )
    	 {
    	  for ( FinishedProduct fp : entry.getValue() )
     	   {
    		Iterator<BaseProduct> iter=fp.getBaseProductList().iterator();
    		while ( iter.hasNext() )
    		 {
    		  BaseProduct bp=iter.next();
     
    	      System.out.println("Produit de base "+bp.getName()+" "+bp);
     
    		 }
     	   }
        }
    Et là baf la référence n'est plus la même....Ci-dessous affichage de la console :

    Produit de base Pâte à pizza menu.BaseProduct@50134894 remplacé par Pâte à pizza menu.BaseProduct@2957fcb0
    bprefmenu.BaseProduct@2957fcb0
    bpmenu.BaseProduct@2957fcb0
    Produit de base Pâte à pizza menu.BaseProduct@50134894

    Cte prise de tête

  5. #5
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Sérieusement, mec, repense à mon bout de code tout con.

    bp c'est juste une variable. Quel effet ça a de donner une autre valeur à une variable ? Aucun effet, bien sûr -_-°.
    Les variables locales ne sont qu'un confort d'écriture, elles ne savent pas qui a fourni les objets qu'on leur donne, et donc ne peuvent pas leur dire de changer leur contenu.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    Citation Envoyé par damtoul Voir le message
    Pour le problème de référence c'est tout con j'ai compris pourquoi mon bp=bpref ne marchait pas, et ça n'a pas à voir avec ton explication : l'affectation se déroule bien, mais évidemment uniquement DANS la fonction.
    En lisant en diagonale, je dirais que lors de la sérialisation, tu sauvegarde tes objets ainsi que leur contenu. Ainsi, lors de la deserialisation, tes objets ingredients sont instanciés pour chaque recette plutot qu'un ingredient global pour toute les recettes. Et c'est ca ton probleme.

    Dans ton cas, ce qu'il faut faire, c'est comme la dit thelvin sauvegarder les ingredients par identifiant plutot qu'en les serialisant (l'id pouvant etre un numero unique ou une chaine mais devant identifier de maniere unique chaque ingredient).
    Lors de la deserialisation, il faut faire correspondre l'identifiant de l'ingredient avec la classe correspondant.
    Mais ca depend de ton architecture. 2 cas:
    1 - Ta liste d'ingredients est hardcodée. Dans ce cas, il te faut une factory qui te retourne l'instance de l'ingredient en fonction de son id
    2 - Tes ingredients aussi sont serialisés. Dans ce cas, il faut lire les ingredients avant les recettes et creer une factory qui te retourne l'instance de l'ingredient en fonction de son id pour la deserialisation de la recette.

  7. #7
    Membre régulier Avatar de damtoul
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juillet 2015
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juillet 2015
    Messages : 60
    Points : 104
    Points
    104
    Par défaut
    @Thelvin : désolé mais je n'arrive pas à te suivre. :/ Dans ton exemple tu me parles d'une variable primitive, moi dans mon code je parle de références sur des objets qui sont différentes. J'ai du mal à faire le // là...

    @hwo : tu as senti le problème.
    En effet, mon problème venait bien de la s/ds car ... les collections de produits de base et de produits finis (qui contenait un ou plusieurs produits de base) étaient dans des instances de classes différentes. Donc forcément à la désérialisation les programme pointait vers de nouvelles références qui étaient cette fois différentes entre les produits de base et les mêmes produits de base présents dans les produits finis. J'ai résolu très simplement le problème en ramenant ma collection de produit de base dans la classe qui contient la collection de produits finis=>tout est instancié dans un même objet et la sérialisation/désérialisation ne cause plus de souci.
    Et effectivement une factory pour récupérer l'instance était une belle solution aussi!

    Merci à tous les deux pour la discussion. : jap :

  8. #8
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Citation Envoyé par damtoul Voir le message
    @Thelvin : désolé mais je n'arrive pas à te suivre. :/ Dans ton exemple tu me parles d'une variable primitive, moi dans mon code je parle de références sur des objets qui sont différentes. J'ai du mal à faire le // là...
    Ben... Il n'y a pas de variable primitive ou non primitive qui tienne. Une variable est une variable. Ça marche pareil quel que soit son type.

    On a qu'à refaire un autre exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    String s = "hello";
    s = "bonjour";
    C'est exactement la même chose, et pourtant ce ne sont pas des primitives. Ça ne change rien au fait que ce bout de code ne va pas partir à la recherche des String "hello" du monde entier pour les remplacer par "bonjour".

    Dans le même genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    LocalDate d = LocalDate.now();
    d = LocalDate.of(2014, 2, 25);
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  9. #9
    Membre régulier Avatar de damtoul
    Homme Profil pro
    Développeur Java
    Inscrit en
    Juillet 2015
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juillet 2015
    Messages : 60
    Points : 104
    Points
    104
    Par défaut
    Ah ok je crois comprendre notre incompréhension! Relis mon bout de code, le est inclus dans une double itération, donc oui tous mes objets bp étaient bien comparés/remplacés par les bpref si égalité de nom.

    De toute manière c'est réglé mon fonction lourdingue et illisible n'a plus lieu d'être.

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

Discussions similaires

  1. Comment casser la référence entre objets ?
    Par krunch dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 25/12/2014, 19h17
  2. [Débutant] Problème de référence d'objet
    Par Romain0 dans le forum VB.NET
    Réponses: 7
    Dernier message: 27/01/2012, 10h15
  3. [EJB3] [Eclipse] problème de références entre un projet EJB et son client
    Par olivier57b dans le forum Java EE
    Réponses: 2
    Dernier message: 17/03/2010, 16h00
  4. Références entre Objets générés
    Par DaveShot dans le forum Eclipse Platform
    Réponses: 1
    Dernier message: 25/08/2009, 09h36
  5. Association entre objet Id ou référence ?
    Par grosFab dans le forum Langages de programmation
    Réponses: 1
    Dernier message: 19/04/2007, 13h41

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