J'ai essentiellement des objets dans cette configuration (le vrai modèle de données est un peu plus complexe):
- A a une relation plusieurs-à-plusieurs avec B. (B a
inverse="true"
) - B a une relation plusieurs-à-un avec C. (je me suis
cascade
mis à"save-update"
) - C est une sorte de table de type / catégorie.
De plus, 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 a un ensemble d'objets B différents, et ces objets B font référence au même objet C.
Quand je l' appelle session.saveOrUpdate(myAObject)
, je reçois une erreur veille prolongée en disant: "a different object with the same identifier value was already associated with the session: C"
. Je sais que hibernate ne peut pas insérer / mettre à jour / supprimer le même objet deux fois dans la même session, mais y a-t-il un moyen de contourner ce problème? Cela ne semble pas être une situation si rare.
Au cours de mes recherches sur ce problème, j'ai vu des gens suggérer l'utilisation de session.merge()
, mais lorsque je fais cela, tous les objets "en conflit" sont insérés dans la base de données en tant qu'objets vides avec toutes les valeurs définies sur null. Ce n'est clairement pas ce que nous voulons.
[Edit] 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 distincte.
Réponses:
C'est probablement parce que les objets B ne font pas référence à la même instance d'objet Java C. Ils font référence à la même ligne dans la base de données (c'est-à-dire à la même clé primaire) mais ils en sont des copies différentes.
Donc, ce qui se passe, c'est que la session Hibernate, qui gère les entités, garderait une trace de quel objet Java correspond à la ligne avec la même clé primaire.
Une option serait de s'assurer que les entités des objets B qui font référence à la même ligne se réfèrent réellement à la même instance d'objet de C. Sinon, désactivez la cascade pour cette variable membre. De cette façon, lorsque B persiste, C ne l'est pas. Vous devrez cependant enregistrer C manuellement séparément. Si C est une table de type / catégorie, alors il est probablement logique d'être de cette façon.
la source
Réglez simplement cascade sur MERGE, cela devrait faire l'affaire.
la source
Vous n'avez besoin de faire qu'une seule chose. Exécutez
session_object.clear()
puis enregistrez le nouvel objet. Cela effacera la session (comme il porte bien son nom) et supprimera l'objet dupliqué incriminé de votre session.la source
Je suis d'accord avec @Hemant Kumar, merci beaucoup. Selon sa solution, j'ai résolu mon problème.
Par exemple:
Person.java
Ce code fait toujours erreur dans mon application:,
A different object with the same identifier value was already associated with the session
plus tard, j'ai découvert que j'avais oublié d' augmenter automatiquement ma clé primaire!Ma solution est d'ajouter ce code sur votre clé primaire:
la source
Cela signifie que vous essayez d'enregistrer plusieurs lignes dans votre table avec la référence au même objet.
vérifiez la propriété id de votre classe d'entité.
à
la source
Transférez la tâche d'attribution de l'ID d'objet d'Hibernate à la base de données en utilisant:
Cela a résolu le problème pour moi.
la source
Ajoutez l'annotation @GeneratedValue au bean que vous insérez.
la source
Une façon de résoudre le problème ci-dessus sera de remplacer le fichier
hashcode()
.Videz également la session de mise en veille prolongée avant et après l'enregistrement.
La définition explicite de l'objet détaché sur est
null
également utile.la source
Je viens de tomber sur ce message mais en code c #. Je ne sais pas si c'est pertinent (exactement le même message d'erreur cependant).
Je déboguais le code avec des points d'arrêt et étendais certaines collections via des membres privés alors que le débogueur était à un point d'arrêt. Après avoir réexécuté le code sans fouiller dans les structures, le message d'erreur disparaît. Il semble que le fait de rechercher dans des collections privées chargées paresseusement ait obligé NHibernate à charger des choses qui n'étaient pas censées être chargées à ce moment-là (car elles étaient dans des membres privés).
Le code lui-même est enveloppé dans une transaction assez compliquée qui peut mettre à jour un grand nombre d'enregistrements et de nombreuses dépendances dans le cadre de cette transaction (processus d'importation).
Espérons un indice pour toute autre personne qui rencontre le problème.
la source
Recherchez l'attribut «Cascade» dans Hibernate et supprimez-le. Lorsque vous définissez "Cascade" disponible, il appellera d'autres opérations (enregistrer, mettre à jour et supprimer) sur une autre entité qui a une relation avec les classes associées. Donc, la même valeur d'identité se produira. Cela a fonctionné avec moi.
la source
J'ai eu cette erreur quelques jours et j'ai trop vite résolu cette erreur.
Avant d'obtenir cette erreur, je n'avais pas mentionné le type de génération d'ID sur l'objet OrderDetil. quand sans générer l'ID de Orderdetails, il garde l'ID à 0 pour chaque objet OrderDetail. c'est ce que #jbx a expliqué. Oui, c'est la meilleure réponse. ceci un exemple comment cela se produit.
la source
Essayez de placer le code de votre requête avant. Cela résout mon problème. par exemple, changez ceci:
pour ça:
la source
vous ne définissez peut-être pas l'identificateur de l'objet avant d'appeler la requête de mise à jour.
la source
J'ai rencontré le problème car la génération de la clé primaire est incorrecte, lorsque j'insère une ligne comme celle-ci:
Je change la classe du générateur d'identifiant en identité
la source
Dans mon cas, seul flush () ne fonctionnait pas. J'ai dû utiliser un clear () après flush ().
la source
si vous utilisez EntityRepository, utilisez saveAndFlush au lieu de save
la source
Si laissé un onglet d'expressions dans mon IDE ouvert qui faisait un appel get hibernate sur l'objet à l'origine de cette exception. J'essayais de supprimer ce même objet. J'ai également eu un point d'arrêt sur l'appel de suppression qui semble être nécessaire pour que cette erreur se produise. Le simple fait de créer un autre onglet d'expressions en tant qu'onglet avant ou de modifier le paramètre pour que l'ide ne s'arrête pas aux points d'arrêt a résolu ce problème.
la source
Assurez-vous que votre entité a le même type de génération avec toutes les entités mappées
Ex: UserRole
}
Module:
}
Entité principale avec mappage
}
la source
En plus de toutes les réponses précédentes, une solution possible à ce problème dans un projet à grande échelle, si vous utilisez un objet de valeur pour vos classes ne définissez pas l'attribut id dans la classe VO Transformer.
la source
validez simplement la transaction en cours.
maintenant vous pouvez commencer une autre transaction et faire n'importe quoi sur l'entité
la source