128 votes

Erreur Hibernate : un objet différent avec la même valeur d'identifiant a déjà été associé à la session.

J'ai essentiellement quelques objets dans cette configuration (le modèle de données réel est un peu plus complexe) :

  • A a une relation de plusieurs à plusieurs avec B. (B a inverse="true" )
  • B a une relation de plusieurs à un avec C. (J'ai cascade réglé sur "save-update" )
  • C est une sorte de tableau de types/catégories.

En outre, je devrais probablement mentionner que les clés primaires sont générées par la base de données lors de la sauvegarde.

Avec mes données, je rencontre parfois des problèmes où A possède un ensemble d'objets B différents, et ces objets B font référence au même objet C.

Quand j'appelle session.saveOrUpdate(myAObject) j'ai une erreur d'hibernation qui dit : "a different object with the same identifier value was already associated with the session: C" . Je sais qu'Hibernate ne peut pas insérer/mettre à jour/supprimer le même objet deux fois dans la même session, mais existe-t-il un moyen de contourner ce problème ? Il semble que cette situation ne soit pas si rare.

Au cours de mes recherches sur ce problème, j'ai vu des personnes suggérer l'utilisation de session.merge() Mais lorsque je fais cela, tous les objets "conflictuels" sont insérés dans la base de données en tant qu'objets vides avec toutes les valeurs définies comme nulles. Il est clair que ce n'est pas ce que nous voulons.

[Une autre chose que j'ai oublié de mentionner est que (pour des raisons architecturales indépendantes de ma volonté), chaque lecture ou écriture doit être effectuée dans une session séparée.

0voto

La raison de ce problème est que vous avez différentes copies d'objets se référant au même raw dans votre table enfant, donc le printemps essaie de traiter votre objet comme un nouvel objet mais lors de l'enregistrement il identifie qu'il y a un raw avec la même clé primaire. Il donne donc l'erreur ci-dessus.

La meilleure solution pour ce problème est de charger l'objet complet (entité parent avec les entités enfants) à partir de la base de données (vous connaissez déjà la clé primaire de l'objet parent), puis de mettre à jour les valeurs dans l'objet chargé à partir de la base de données à partir de votre nouvel objet (que vous essayez de sauvegarder) et enfin de sauvegarder l'objet que vous avez chargé à partir de la base de données qui a de nouvelles valeurs.

Cela mettra à jour vos valeurs dans la base de données sans donner l'erreur ci-dessus.

PS- Il n'est pas nécessaire de mettre à jour les identifiants car ils existent déjà dans l'objet chargé depuis la base de données, il suffit de mettre à jour les valeurs qui doivent être modifiées.

0voto

user1587329 Points 91

Une autre façon de résoudre ce problème est d'utiliser les données du printemps :

  • remplacer les appels à entityManager.persist() avec des appels à repository.save() et
  • remplacer les appels à entityManager.query().getResultList() etc. avec des appels à repository.findBy...

De cette façon, les données du printemps gardent la trace des objets. Il permet de multiples appels get et persist.

0voto

Asharudheen Mt Points 1

Au lieu de simplement @Id essayez @Id @Valeur générée(stratégie = GenerationType.AUTO) cela a fonctionné pour moi

0voto

Khasan 24-7 Points 386

Dans mon cas, j'avais une relation OneToOne et après avoir enregistré une ligne avec une clé étrangère, j'ai essayé d'enregistrer une autre ligne avec la même clé étrangère, ce qui a provoqué la même exception. Cela signifie que l'exigence n'était pas une relation OneToOne, mais devrait être ManyToOne. Je l'ai donc changé en ManyToOne et cela a commencé à fonctionner.

0voto

Blas Albir Points 1

Cette erreur se produit généralement parce que vous violez une colonne de type unique ou une clé primaire lorsque vous essayez d'insérer des données répétées.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X