Quelles sont les différences entre les différentes méthodes d'épargne en hibernation?

Hibernate a une poignée de méthodes qui, d'une manière ou d'une autre, prend l'objet et le met dans la base de données. Quelles sont les différences entre eux, quand à utiliser, et pourquoi n'est-il pas juste une méthode intelligente qui sait quand utiliser quoi?

les méthodes que j'ai identifiées jusqu'à présent sont:

  • save()
  • update()
  • saveOrUpdate()
  • saveOrUpdateCopy()
  • merge()
  • persist()
183
demandé sur shA.t 2008-10-02 11:38:12

8 réponses

Voici ma compréhension des méthodes. Principalement ceux-ci sont basés sur le API bien que je ne les utilise pas tous dans la pratique.

saveOrUpdate Appels soit enregistrer ou mettre à jour en fonction de certaines vérifications. E. g. si aucun identifiant n'existe, save est appelée. Sinon mise à jour est appelée.

enregistrer Persiste une entité. Assignera un identifiant si celui-ci n'existe pas. Si l'on le fait, c'est essentiellement de faire une mise à jour. Retourne l'IDENTIFIANT généré de l'entité.

mise à jour Tente de maintenir l'entité en utilisant un identificateur existant. Si aucun identificateur n'existe, je crois qu'une exception est lancée.

saveOrUpdateCopy Ceci est déprécié et ne devrait plus être utilisé. Au lieu de cela, il est...

fusion Maintenant c'est là que ma connaissance commence faiblir. L'important ici est la différence entre les entités transitoires, détachées et persistantes. Pour plus d'informations sur les états de l'objet, jetez un oeil ici . Avec save & update, vous avez affaire à des objets persistants. Ils sont liés à une Session de sorte que Hibernate sait ce qui a changé. Mais quand vous avez un objet transitoire, il n'y a pas de session impliquée. Dans ces cas, vous devez utiliser merge pour les mises à jour et persister pour sauvegarder.

persist Comme mentionné ci-dessus, ceci est utilisé sur les objets transitoires. Elle ne retourne l'IDENTIFIANT généré.

109
répondu Lee Theobald 2015-02-18 20:10:15
╔══════════════╦═══════════════════════════════╦════════════════════════════════╗
║    METHOD    ║            TRANSIENT          ║            DETACHED            ║
╠══════════════╬═══════════════════════════════╬════════════════════════════════╣
║              ║       sets id if doesn't      ║   sets new id even if object   ║
║    save()    ║     exist, persists to db,    ║    already has it, persists    ║
║              ║    returns attached object    ║ to DB, returns attached object ║
╠══════════════╬═══════════════════════════════╬════════════════════════════════╣
║              ║       sets id on object       ║             throws             ║
║   persist()  ║     persists object to DB     ║       PersistenceException     ║
║              ║                               ║                                ║
╠══════════════╬═══════════════════════════════╬════════════════════════════════╣
║              ║                               ║                                ║
║   update()   ║           Exception           ║     persists and reattaches    ║
║              ║                               ║                                ║
╠══════════════╬═══════════════════════════════╬════════════════════════════════╣
║              ║  copy the state of object in  ║    copy the state of obj in    ║
║    merge()   ║     DB, doesn't attach it,    ║      DB, doesn't attach it,    ║
║              ║    returns attached object    ║     returns attached object    ║
╠══════════════╬═══════════════════════════════╬════════════════════════════════╣
║              ║                               ║                                ║
║saveOrUpdate()║           as save()           ║            as update()         ║
║              ║                               ║                                ║
╚══════════════╩═══════════════════════════════╩════════════════════════════════╝
111
répondu Sergii Shevchyk 2013-09-03 20:30:57
  • voir le Hibernate Forum pour une explication des différences subtiles entre persist et save. Il semble que la différence soit le moment où L'instruction INSERT est finalement exécutée. Puisque save retourne l'identifiant, L'instruction INSERT doit être exécutée instantanément quel que soit l'état de la transaction (ce qui est généralement une mauvaise chose). Persist ne pas exécuter n'importe quelle des déclarations en dehors de la transaction en cours d'exécution juste pour assigner l'identifiant. Enregistrer / persister les deux travaux sur instances transitoires , c'est-à-dire les instances qui n'ont pas encore d'identificateur assigné et ne sont donc pas enregistrés dans le DB.

  • mise à Jour et Fusion à la fois le travail sur des instances détachées , c'est à dire les instances qui ont une entrée correspondante dans la base de données mais qui ne sont pas actuellement rattachés à (ou gérés par) une Session. La différence entre eux est ce qui arrive à l'instance qui est passée à la fonction. update tente de rattacher l'instance, ce qui signifie qu'il ne peut y avoir aucune autre instance de l'entité persistante attachée à la Session en ce moment sinon une exception est lancée. merge , cependant, copie juste toutes les valeurs à une instance persistante dans la Session (qui sera chargée si elle n'est pas actuellement chargée). L'entrée de l'objet n'est pas modifié. Donc fusionner est plus général que mettre à jour , mais peut utiliser plus de ressources.

65
répondu jrudolph 2008-10-02 09:05:00

Ce lien qui explique en bonne manière :

http://www.stevideter.com/2008/12/07/saveorupdate-versus-merge-in-hibernate /

nous avons tous ces problèmes que nous rencontrons juste assez rarement que lorsque nous les voyons à nouveau, nous savons que nous avons résolu ceci, mais ne peut pas se rappeler comment.

La NonUniqueObjectException jeté lors de l'utilisation de Session.saveOrUpdate() en mode veille prolongée est l'un des miens. Je vais être en ajoutant nouvelle fonctionnalité pour une application complexe. Tous les tests de mon unité marchent bien. Puis en testant L'UI, en essayant de sauver un objet, je commence à obtenir une exception avec le message "un objet différent avec la même valeur d'identification était déjà associé à la session."Voici un exemple de code de Java Persistence avec Hibernate.

            Session session = sessionFactory1.openSession();
            Transaction tx = session.beginTransaction();
            Item item = (Item) session.get(Item.class, new Long(1234));
            tx.commit();
            session.close(); // end of first session, item is detached

            item.getId(); // The database identity is "1234"
            item.setDescription("my new description");
            Session session2 = sessionFactory.openSession();
            Transaction tx2 = session2.beginTransaction();
            Item item2 = (Item) session2.get(Item.class, new Long(1234));
            session2.update(item); // Throws NonUniqueObjectException
            tx2.commit();
            session2.close();

pour comprendre la cause de cette exception, il est important de comprendre les objets détachés et ce qui se passe quand vous appelez saveOrUpdate () (ou tout simplement update ()) sur un objet détaché.

lorsque nous fermons une session D'hibernation individuelle, les objets persistants avec lesquels nous travaillons sont détachés. Cela signifie que les données sont toujours dans la mémoire de l'application, mais Hibernate n'est plus responsable du suivi des modifications apportées aux objets.

si nous modifions alors notre objet détaché et que nous voulons le mettre à jour, nous devons rattacher l'objet. Au cours de ce processus de rattachement, hibernation vérifiera voyez s'il y a d'autres copies du même objet. S'il en trouve, il doit nous dire qu'il ne sait plus ce qu'est la "vraie" copie. Peut-être que d'autres changements ont été apportés à ces autres copies que nous espérons sauvegarder, mais Hibernate ne sait pas à leur sujet, parce qu'il ne les gérait pas à l'époque.

plutôt que d'enregistrer des données potentiellement mauvaises, Hibernate nous parle du problème via la NonUniqueObjectException.

alors que faire? Dans Hibernate 3, nous avons merge() (dans Hibernate 2, utilisez saveOrUpdateCopy()). Cette méthode forcera Hibernate à copier tout changement d'autres instances détachées sur l'instance que vous voulez enregistrer, et fusionne ainsi tous les changements dans la mémoire avant la sauvegarde.

        Session session = sessionFactory1.openSession();
        Transaction tx = session.beginTransaction();
        Item item = (Item) session.get(Item.class, new Long(1234));
        tx.commit();
        session.close(); // end of first session, item is detached

        item.getId(); // The database identity is "1234"
        item.setDescription("my new description");
        Session session2 = sessionFactory.openSession();
        Transaction tx2 = session2.beginTransaction();
        Item item2 = (Item) session2.get(Item.class, new Long(1234));
        Item item3 = session2.merge(item); // Success!
        tx2.commit();
        session2.close();

il est important de noter que merge renvoie une référence à la version nouvellement mise à jour de l'instance. Ce n'est pas rattacher un point à la Session. Si vous testez par exemple l'égalité (item == item3), vous trouverez renvoie la valeur false dans le cas présent. Vous voudrez probablement travailler avec item3 à partir de ce point.

il est également important de noter que L'API Java Persistence (JPA) n'a pas de concept d'objets détachés et attachés de nouveau, et utilise EntityManager.persist() et EntityManager.fusionner.)(

j'ai trouvé en général que lorsque j'utilise Hibernate, saveOrUpdate() est généralement suffisant pour mes besoins. Je n'ai habituellement besoin d'utiliser la fusion que lorsque j'ai des objets qui peuvent avoir les références à des objets de même type. Plus récemment, la cause de l'exception était dans le code validant que la référence n'était pas récursive. Je chargeais le même objet dans ma session dans le cadre de la validation, provoquant l'erreur.

Où avez-vous rencontré ce problème? Avez-fusionner le travail pour vous ou avez-vous besoin d'une autre solution? Préférez-vous toujours utiliser merge, ou préférez-vous l'utiliser seulement comme nécessaire pour des cas spécifiques

11
répondu HakunaMatata 2013-10-15 13:02:50

en fait, la différence entre les méthodes d'hibernation save() et persist() dépend de la classe de la génératrice que nous utilisons.

si notre classe de groupe électrogène est attribuée, il n'y a pas de différence entre les méthodes save() et persist( ). Parce que générateur " assigné’ signifie, en tant que programmeur, nous avons besoin de donner la valeur clé primaire pour enregistrer dans la base de données droit [ J'espère que vous connaissez ce concept de générateurs ] Dans le cas d'une classe de générateur autre que celle qui est assignée, supposons que si notre nom de classe de générateur est Increment signifie hibernate, il se assignera lui-même la valeur de l'id de la clé primaire dans la base de données à droite [ autre que générateur assigné, hibernate utilisé seulement pour prendre soin de la valeur de l'id de la clé primaire se rappeler ], donc dans ce cas, si nous appelons save() ou persist() méthode alors il insérera l'enregistrement dans la base de données normalement Mais la chose d'entendre est, save() méthode peut retourner cette clé primaire id valeur qui est générée par hibernate et nous pouvons le voir par

long s = session.save(k);

dans ce même cas, persist() ne rendra jamais aucune valeur au client.

4
répondu Hari Krishna 2012-04-11 08:07:41

j'ai trouvé un bon exemple montrant les différences entre toutes les méthodes de sauvegarde hibernate:

http://www.journaldev.com/3481/hibernate-session-merge-vs-update-save-saveorupdate-persist-example

en résumé, selon le lien ci-dessus:

save ()

  • nous pouvons invoquer cette méthode en dehors d'une transaction. Si nous utilisons ce sans transaction et nous avons la cascade entre les entités, alors seulement l'entité principale est sauvée à moins que nous vidons la session.
  • ainsi, s'il y a d'autres objets mappés à partir de l'objet principal, ils sont sauvegardés au moment de la transaction de propagation ou lorsque nous vidons la session.

persist ()

  • C'est similaire à utiliser save() dans la transaction, donc il est sûr et prend soin de tout en cascade des objets.

saveOrUpdate ()

  • peut être utilisé avec ou sans la transaction, et tout comme save(), si elle est utilisée sans la transaction, les entités mappées ne seront pas sauvegardées un;ess nous vidons la session.

  • résultats dans insérer ou mettre à jour des requêtes basées sur les données fournies. Si les données sont présentes dans la base de données, update query est exécuter.

update ()

  • la mise à jour D'hibernation doit être utilisée lorsque nous savons que nous ne faisons que mettre à jour les informations de l'entité. Cette opération ajoute l'objet entité au contexte persistant et d'autres changements sont suivis et sauvegardés lorsque la transaction est engagée.
  • donc même après avoir appelé update, si nous définissons des valeurs dans l'entity,elles seront mises à jour quand validation de transaction.

merge ()

  • la fusion Hibernate peut être utilisée pour mettre à jour les valeurs existantes, mais cette méthode crée une copie de l'objet entité passé et la renvoie. L'objet retourné fait partie du contexte persistant et fait l'objet d'un suivi pour tout changement, l'objet passé n'est pas suivi. C'est la différence majeure avec merge() de toutes les autres méthodes.

également pour exemples pratiques de toutes ces méthodes, veuillez vous référer au lien que j'ai mentionné ci-dessus, il montre des exemples pour toutes ces différentes méthodes.

4
répondu OutOfMind 2017-04-12 06:53:11

sachez que si vous appelez une mise à jour sur un objet détaché, il y aura toujours une mise à jour dans la base de données que vous ayez changé l'objet ou non. Si ce n'est pas ce que vous voulez, vous devriez utiliser Session.lock () avec LockMode.Aucun.

vous ne devez appeler update que si l'objet a été modifié en dehors de la portée de votre session actuelle (en mode détaché).

2
répondu bernardn 2008-10-03 12:13:20

aucune des réponses suivantes n'est correcte. Toutes ces méthodes semblent être identiques, mais dans la pratique font des choses absolument différentes. Il est difficile de donner des commentaires. Mieux de donner un lien vers une documentation complète sur ces méthodes: http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/objectstate.html

1
répondu Anton Popovich 2012-10-26 10:38:45