web-dev-qa-db-fra.com

Références partagées d'une collection org.hibernate.HibernateException

J'ai eu ce message d'erreur:

erreur: trouvé des références partagées à une collection: Person.relatedPersons

Quand j'ai essayé d'exécuter addToRelatedPersons(anotherPerson):

person.addToRelatedPersons(anotherPerson);
anotherPerson.addToRelatedPersons(person);

anotherPerson.save();
person.save();

Mon domaine:

Person {

 static hasMany = [relatedPersons:Person];

}

aucune idée pourquoi cela se produit?

48
nightingale2k1

Hibernate affiche cette erreur lorsque vous essayez de conserver plusieurs instances d'entités partageant la référence même collection (c'est-à-dire l'identité de la collection par opposition à son égalité).

Notez que cela signifie la même chose collection , pas un élément de la collection - en d’autres termes, relatedPersons sur person et anotherPerson doit être identique. Peut-être que vous réinitialisez cette collection après le chargement des entités? Ou vous avez initialisé les deux références avec la même instance de collection?

55
ChssPly76

J'ai eu le même problème. Dans mon cas, le problème était que quelqu'un utilisait BeanUtils pour copier les propriétés d'une entité à une autre. Nous avons donc fini par avoir deux entités référençant la même collection.

Étant donné que j'ai passé quelque temps à enquêter sur ce problème, je recommanderais la liste de contrôle suivante:

  • Recherchez des scénarios tels que entity1.setCollection(entity2.getCollection()) et getCollection renvoie la référence interne à la collection (si getCollection () renvoie une nouvelle instance de la collection, vous n'avez pas à vous inquiéter).

  • Regardez si clone() a été implémenté correctement.

  • Recherchez BeanUtils.copyProperties(entity1, entity2).

45
dgt

Explication sur la pratique. Si vous essayez de sauvegarder votre objet, par exemple:

Set<Folder> folders = message.getFolders();
   folders.remove(inputFolder);
   folders.add(trashFolder);
   message.setFiles(folders);
MESSAGESDAO.getMessageDAO().save(message);

vous n'avez pas besoin de définir l'objet mis à jour sur un objet parent:

message.setFiles(folders);

Enregistrez simplement votre objet parent comme:

Set<Folder> folders = message.getFolders();
   folders.remove(inputFolder);
   folders.add(trashFolder);
   // Not set updated object here
MESSAGESDAO.getMessageDAO().save(message);
4
Mirimas

La lecture en ligne de la cause de cette erreur peut aussi être un bogue hibernate, comme solution de contournement qui semble fonctionner, il faut mettre un:

session.clear()

Vous devez mettre le clear après avoir récupéré les données et avant de valider et de fermer, voir exemple:

//getting data
SrReq sr = (SrReq) crit.uniqueResult();
SrSalesDetailDTO dt=SrSalesDetailMapper.INSTANCE.map(sr);
//CLEAR            
session.clear();
//close session
session.getTransaction().commit();
session.close();
return dt;

J'utilise cette solution pour sélectionner la base de données, pour la mise à jour ou pour l'insertion. Je ne sais pas si cette solution peut fonctionner ou causer des problèmes.

Mon problème est égal à 100% de cela: http://www.progtown.com/topic128073-hibernate-many-to-many-on-two-tables.html

2
Diego87

Dans mon cas, je copiais et collais du code de mes autres classes, donc je n’ai pas remarqué que le code de lecture était mal écrit:

@OneToMany(fetch = FetchType.LAZY, mappedBy = "credito")
public Set getConceptoses() {
    return this.letrases;
}

public void setConceptoses(Set conceptoses) {
    this.conceptoses = conceptoses;
}

Toutes les référencesconceptosesmais si vous regardez le get ditletrases

2
John Lopez

Moi aussi j'ai eu le même problème, quelqu'un a utilisé BeanUtils.copyProperties(source, target). Ici, source et cible, utilisent la même collection en tant qu'attribut. 

Donc, je viens d'utiliser la copie en profondeur comme ci-dessous ..

Comment cloner une collection en Java - Copie complète d'ArrayList et de HashSet

1
raji

J'ai fait face à une exception similaire dans ma candidature. Après avoir examiné la pile, il était clair que cette exception avait été générée dans une classe FlushEntityEventListener.

Dans Hibernate 4.3.7, le bean MSLocalSessionFactory ne supporte plus la propriété eventListeners. Par conséquent, il est nécessaire d'extraire explicitement le registre de service des beans de session Hibernate individuels, puis de définir les écouteurs d'événements personnalisés requis.

Lors de l'ajout d'écouteurs d'événements personnalisés, nous devons nous assurer que les écouteurs d'événements par défaut correspondants sont supprimés de la session Hibernate respective.

Si l'écouteur d'événements par défaut n'est pas supprimé, deux écouteurs d'événements enregistrés pour le même événement se présentent. Dans ce cas, lors d'une itération sur ces écouteurs, contre les premiers écouteurs, toutes les collections de la session seront marquées comme atteintes et, lors du traitement de la même collection contre le deuxième auditeur, cette exception Hibernate sera levée.

Assurez-vous donc que lors de l'enregistrement des écouteurs personnalisés, les écouteurs par défaut correspondants sont supprimés du registre.

0
Dinesh Angolkar