web-dev-qa-db-fra.com

JPA fusion vs persist

Jusqu'à présent, ma préférence a toujours été d'utiliser merge() de EntityManager pour prendre en charge l'insertion et la mise à jour. Mais j'ai aussi remarqué que la fusion effectue une sélection de requêtes supplémentaires avant la mise à jour/l'insertion pour s'assurer que l'enregistrement n'existe pas déjà dans la base de données.

Maintenant que je travaille sur un projet nécessitant de nombreuses insertions (en masse) dans la base de données. Du point de vue des performances, est-il logique d’utiliser persist au lieu de fusionner dans un scénario où je sais absolument que je crée toujours une nouvelle instance d’objets à conserver?

66
phewataal

Ce n'est pas une bonne idée d'utiliser merge lorsqu'un suffixe persist - merge fait beaucoup plus de travail. Le sujet a été discuté sur StackOverflow avant, et cet article explique en détail les différences, avec quelques organigrammes de Nice pour clarifier les choses.

69
Óscar López

J'irais certainement avec persist persist() si, comme vous l'avez dit:

(...) Je sais absolument que je crée toujours une nouvelle instance d'objets à conserver (...)

C’est le but de cette méthode: elle vous protégera dans les cas où l’entité existe déjà (et annulera votre transaction).

9
Piotr Nowicki

Si vous utilisez le générateur affecté, tiliser merge à la place de persist peut provoquer une instruction SQL redondante , affectant ainsi les performances.

En outre, fusion d'appel pour les entités gérées est également une erreur, car les entités gérées sont automatiquement gérées par Hibernate et leur état est synchronisé avec l'enregistrement de la base de données par le mécanisme de vérification à blanc après - effacement du contexte de persistance .

Pour comprendre comment tout cela fonctionne, vous devez d’abord savoir que Hibernate fait passer l’état de développement des instructions SQL à transitions d’état .

Une fois qu'une entité est activement gérée par Hibernate, toutes les modifications seront automatiquement propagées à la base de données.

Hibernate surveille les entités actuellement attachées. Mais pour qu'une entité soit gérée, elle doit être dans le bon état.

Tout d'abord, nous devons définir tous les états d'entité:

  • Nouveau (transitoire)

    Un objet nouvellement créé qui n’a jamais été associé à un Hibernate Session (a.k.a Persistence Context) et n'est mappé sur aucune ligne de la table de la base de données est considérée comme étant à l'état Nouveau (transitoire).

    Pour devenir persistants, nous devons soit appeler explicitement le EntityManager#persist méthode ou utilisez le mécanisme de persistance transitive.

  • Persistant (géré)

    Une entité persistante a été associée à une ligne de table de base de données et est gérée par le contexte de persistance en cours d’exécution. Toute modification apportée à cette entité sera détectée et propagée à la base de données (pendant le temps de session). Avec Hibernate, nous n’avons plus besoin d’exécuter les instructions INSERT/UPDATE/DELETE. Hibernate utilise un style de travail écriture transactionnelle transactionnelle et les modifications sont synchronisées au tout dernier moment responsable, pendant le Session jour actuel.

  • Détaché

    Une fois que le contexte de persistance en cours d'exécution est fermé, toutes les entités précédemment gérées sont détachées. Les modifications successives ne seront plus suivies et aucune synchronisation automatique de la base de données ne sera effectuée.

    Pour associer une entité détachée à une session Hibernate active, vous pouvez choisir l'une des options suivantes:

    • Rattachement

      Hibernate (mais pas JPA 2.1) prend en charge la reconnexion au moyen de la méthode de mise à jour de la session. Une session Hibernate ne peut associer qu'un seul objet Entity pour une ligne de base de données donnée. En effet, le contexte de persistance agit en tant que cache en mémoire (cache de premier niveau) et une seule valeur (entité) est associée à une clé donnée (type d'entité et identificateur de base de données). Une entité ne peut être rattachée que si aucun autre objet JVM (correspondant à la même ligne de la base de données) n'est déjà associé à la session Hibernate en cours.

    • Fusionner

    La fusion va copier l'état de l'entité détachée (source) dans une instance d'entité gérée (destination). Si l'entité en fusion n'a pas d'équivalent dans la session en cours, l'un d'entre eux sera extrait de la base de données. L'instance d'objet détaché continuera à rester détachée même après l'opération de fusion.

  • Enlevé

    Bien que JPA demande que seules les entités gérées soient autorisées à être supprimées, Hibernate peut également supprimer les entités détachées (mais uniquement via un appel à la méthode Session # delete). Une entité supprimée est uniquement programmée pour être supprimée et l'instruction DELETE de la base de données proprement dite sera exécutée au cours du temps de session.

Pour mieux comprendre les transitions d'état JPA, vous pouvez visualiser le diagramme suivant:

enter image description here

Ou si vous utilisez l'API spécifique d'Hibernate:

enter image description here

2
Vlad Mihalcea