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 :

Enregistrer ou mettre à jour une entrée avec Hibernate


Sujet :

Hibernate Java

  1. #1
    Membre régulier Avatar de Palsajicoco
    Étudiant
    Inscrit en
    Février 2007
    Messages
    229
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2007
    Messages : 229
    Points : 84
    Points
    84
    Par défaut Enregistrer ou mettre à jour une entrée avec Hibernate
    Salut,
    J'ai une petite confusion au niveau de hibernate quand je veux enregistrer ou mettre a jour une donnée
    La methode merge et saveor update doivent enregistrer une entree si elle n'existe pas ou bien la mettre a jour a ce que j'ai lu des documentations. Je galere depuis un moment pour la faire marcher mais ca ne marche jamais, quand une entree existe deja, ca la met pas a jours et ca remet une erreur
    Voici le code expliqué:

    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
    Location loc = new Location();
    LocationHome locHome = new LocationHome();
    loc.setName("Annemasse");
    logger.info(anotherLoc.getLocationId()); // Prints NULL
    logger.info(anotherLoc.getName()); // Prints "Annemasse"
    logger.info(anotherLoc.getLat()); // Prints NULL
    loc = locHome.insertUpdate(loc);
    // a ce niveau, la base de donnee contient location Annemasse et disant que le 
    // location_id alloué par mysql est 1
    logger.info(logger.infoanotherLoc.getLocationId()); // Prints 1
    logger.info(anotherLoc.getName()); // Prints "Annemasse"
    logger.info(anotherLoc.getLat()); // Prints NULL
    ////////////////////////////////////////////////////////////////
     
    // une autre execution dans le meme programme ou meme un autre programme
     
    ////////////////////////////////////////////////////////////////
    Location anotherLoc = new Location();
    anotherLoc.setName("Annemasse");
    anotherLoc.setLat("12.02482");
    // a ce point la base contient deja une location avec un nom 
    "Annemasse"
    anotherLoc = locHome.insertUpdate(anotherLoc);
    // Ici je devrai avoir aucune erreur, il devrai mettre a jour la location avec le meme nom
    // mais en executant insertOrUpdate (merge, saveOrUpdate)
    // ca remet une erreur a chaque fois disant duplicated entry ..
     
    logger.info(anotherLoc.getLocationId()); // Prints 1
    logger.info(anotherLoc.getName()); // Prints "Annemasse"
    logger.info(anotherLoc.getLat()); // Prints "12.02482"
    Je ne sais pas si Hibernate bug ou c'est un probleme chez moi :/

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

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Hibernate ne bug pas, tout du moins pas là.
    Tu crées un nouvel objet, donc c'est normal qu'il te crée une nouvelle entrée en base de données.

    Donc, soit dans ton exemple, tu passes la même référence à ton objet LocationHome à ta méthode de modification.
    Soit tu récupères l'objet en question via un session.load ou session.get avant de tenter de le modifier.

  3. #3
    Membre régulier Avatar de Palsajicoco
    Étudiant
    Inscrit en
    Février 2007
    Messages
    229
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2007
    Messages : 229
    Points : 84
    Points
    84
    Par défaut
    Merci pour la réponse,
    Je donne plus de code pour que ça soit plus clair:

    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
    	public void attachDirty(Location instance) {
    		log.debug("attaching dirty Location instance");
    		sessionFactory.getCurrentSession().beginTransaction();
     
    		try {
    			sessionFactory.getCurrentSession().saveOrUpdate(instance);
    			log.debug("attach successful");
    		} catch (RuntimeException re) {
    			log.error("attach failed");
    			throw re;
    		}
     
    		sessionFactory.getCurrentSession().getTransaction().commit();
    	}
     
    	public Location merge(Location detachedInstance) {
    		log.debug("merging Location instance");
    		sessionFactory.getCurrentSession().beginTransaction();
     
    		try {
    			Location result = (Location) sessionFactory.getCurrentSession()
    					.merge(detachedInstance);
    			log.debug("merge successful");
    			sessionFactory.getCurrentSession().getTransaction().commit();
     
    			return result;
    		} catch (RuntimeException re) {
    			log.error("merge failed");
    			throw re;
    		}
    	}
    c'est les méthodes dans Location Home qui sont supposé faire le save ou update, mais rien ne marche. le save marche mais le update remet un duplicated enty qui n'est pas logique du tout, puisque on parle de merge et save OR update :/

  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
    Bonjour,,

    Le fonctionnement de saveOrUpdate() est:
    • s'il n'existe aucun objet en base avec le même Id (ou si l'Id de l'objet passé est null) l'objet est ajouté a la session et il sera inséré lors du flush (ou du commit)
    • s'il existe déjà un objet en base avec le même Id que l'objet passé en paramètre alors l'objet sera rattaché et la ligne sera updatée lors du prochain flush (ou du commit)


    Donc si l'objet qui lui est passé a son Id qui est null alors une nouvelle ligne sera toujours insérée.

  5. #5
    Membre régulier Avatar de Palsajicoco
    Étudiant
    Inscrit en
    Février 2007
    Messages
    229
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2007
    Messages : 229
    Points : 84
    Points
    84
    Par défaut
    Bon, c'est pas du tout ça en pratique, voici ce que je teste:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Location loc = new Location();
    		Location loc2 = new Location();
    		LocationHome locHome = new LocationHome();
    		loc.setName("mohamed");
    		locHome.attachDirty(loc);
                    //locHome.merge(loc);
    pour la premiere execution, il insere dans la base, mais pour la deuxieme, comme kles requetes SQL classiques enfin, si il existe et le meme il ne fait rien, sinon il update. la deuxieme execution donne:

    10:55:54,416 WARN JDBCExceptionReporter:233 - SQL Error: 1062, SQLState: 23000
    10:55:54,416 ERROR JDBCExceptionReporter:234 - Duplicate entry 'xxxxx' for key 2
    10:55:54,417 ERROR LocationHome:57 - attach failed
    alors que c'est pas du tout la même logique du fonctionnement de la méthode.

  6. #6
    Membre actif Avatar de amadoulamine1
    Inscrit en
    Avril 2005
    Messages
    260
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 260
    Points : 270
    Points
    270
    Par défaut
    Salut ce que les autres essaient de te dire c'est dans le second au lieu de mettre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Location anotherLoc = new Location();
    anotherLoc.setName("Annemasse");
    anotherLoc.setLat("12.02482");
    // a ce point la base contient deja une location avec un nom 
    "Annemasse"
    anotherLoc = locHome.insertUpdate(anotherLoc);
    de mettre plutot
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Location anotherLoc = locHome.findByName("Annemasse");
    anotherLoc.setLat("12.02482");
    anotherLoc = locHome.insertUpdate(anotherLoc);
    EDIT : en supposant que tu as implemente la methode findByName

    parceque quand tu as fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    anotherLoc=new Location()
    il te cree une loc avec un id "vide" et c'est un nouveau objet qui n'a rien a voir avec celui sauve donc un saveorUpdate va effectuer un "save" ce qui est normal vu que l'objet n'existe pas dans la table mais en sauvant il va te générer une sql__exception vu qu'une entree avec ce nom existe deja!

  7. #7
    Membre régulier Avatar de Palsajicoco
    Étudiant
    Inscrit en
    Février 2007
    Messages
    229
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2007
    Messages : 229
    Points : 84
    Points
    84
    Par défaut
    Merci pour vos réponses,

    J'ai enfin pu éviter ce problème en codant ma propre insertOrUpdate()
    le truc est chercher dans l'objet a ajouter ou modifier s'il contient un id, on fait update, sinon on cherche s'il y a un entrée unique (par nom par expl), on lui ajoute l'id et on update. Sinon on save. Voila =)

    En fait, le problème n'est pas parfaitement résolu .. je pense qu'il y a un problème de gestion de mémoire. quand j’exécute le programme pour la première fois pour de nouvelles entrées il n'y a pas de problèmes. mais quand j’exécute une autre fois, il crache en disant:

    14:27:54,953 WARN SettingsFactory:147 - Could not obtain connection to query metadata
    com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too many connections"
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)

    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.HashMap.<init>(HashMap.java:209)
    at java.util.HashSet.<init>(HashSet.java:86)
    at org.hibernate.sql.SelectFragment.toFragmentString(SelectFragment.java:140)
    at ....
    Voici mes méthodes:

    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
    	public Location update(Location location) {
    		long locaitonId = location.getLocationId();
    		log.debug("merging Location instance");
     
    		Session sess = null;
     
    		try {
    			SessionFactory fact = new Configuration().configure()
    					.buildSessionFactory();
    			sess = fact.openSession();
     
    			Transaction tr = sess.beginTransaction();
    			Location loc = (Location) sess.get(Location.class, locaitonId);
    			loc.setAddressId(location.getAddressId());
    			loc.setAltitude(location.getAltitude());
    			loc.setLat(location.getLat());
    			loc.setLng(location.getLng());
    			loc.setName(location.getName());
    			sess.update(loc);
    			tr.commit();
    			sess.close();
    			log.debug("update successful");
     
    			return loc;
    		} catch (RuntimeException re) {
    			log.error("update failed");
    			throw re;
    		}
    	}
     
    	public Location insertOrUpdate(Location location) {
    		log.debug("merging Location instance");
     
    		Location locTstName = findByName(location.getName());
     
    		if (location.getLocationId() != null) {
    			Location loc = update(location);
     
    			return loc;
    		} else if (locTstName != null) {
    			location.setLocationId(locTstName.getLocationId());
     
    			Location loc = update(location);
     
    			return loc;
    		} else {
    			Location loc = merge(location);
     
    			return loc;
    		}
    	}
    Le problème réside dans la fonction update puisque pour la première fois il ne crache pas, mais ou exactement .. j'arrive pas a trouver

Discussions similaires

  1. Réponses: 6
    Dernier message: 08/02/2012, 17h18
  2. [AC-2003] Mettre à jour une table avec une variable
    Par nawakbling dans le forum VBA Access
    Réponses: 1
    Dernier message: 02/04/2010, 11h33
  3. [MySQL] Mettre à jour une table avec plusiers tables
    Par lez-j dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 13/02/2010, 22h37
  4. Réponses: 4
    Dernier message: 07/08/2008, 16h10
  5. Réponses: 3
    Dernier message: 18/07/2006, 18h37

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