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

Fawad Khaliq Points 89

Il se peut que vous ne définissiez pas l'identifiant de l'objet avant d'appeler la requête de mise à jour.

0voto

张云风 Points 1

J'ai rencontré le problème parce que la génération de la clé primaire est erronée, lorsque j'insère une ligne comme ceci :

public void addTerminal(String typeOfDevice,Map<Byte,Integer> map) {
        // TODO Auto-generated method stub
        try {
            Set<Byte> keySet = map.keySet();
            for (Byte byte1 : keySet) {
                Device device=new Device();
                device.setNumDevice(DeviceCount.map.get(byte1));
                device.setTimestamp(System.currentTimeMillis());
                device.setTypeDevice(byte1);
                this.getHibernateTemplate().save(device);
            }
            System.out.println("hah");
        }catch (Exception e) {
            // TODO: handle exception
            logger.warn("wrong");
            logger.warn(e.getStackTrace()+e.getMessage());
        }
}

Je change la classe du générateur d'identité en identité

<id name="id" type="int">
    <column name="id" />
    <generator class="identity"  />
 </id>

0voto

Si vous utilisez EntityRepository alors utilisez saveAndFlush au lieu de save

0voto

Aaron Byrnes Points 1

J'ai laissé ouvert un onglet d'expressions dans mon IDE qui faisait un appel get d'Hibernate sur l'objet causant cette exception. J'essayais de supprimer ce même objet. J'avais également un point d'arrêt sur l'appel de suppression qui semble être nécessaire pour que cette erreur se produise. En créant simplement un autre onglet d'expressions pour être l'onglet principal ou en changeant le paramètre pour que l'IDE ne s'arrête pas sur les points d'arrêt, j'ai résolu le problème.

0voto

George Michael Points 1

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 Value Object pour vos classes, ne définissez pas l'attribut id dans la classe VO Transformer.

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