J'ai trouvé des références partagées à un organisme de collecte.hiberner.HibernateException

j'ai eu ce message d'erreur:

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

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

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

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

Mon nom de domaine:

Person {

 static hasMany = [relatedPersons:Person];

}

aucune idée pourquoi cela se produit ?

45
demandé sur Rubens Mariuzzo 2009-11-07 15:27:26

8 réponses

Hibernate montre cette erreur lorsque vous tentez de persister plus d'une instance d'entity partageant le référence de la collection (c.-à-d. l'identité de la collection par opposition à l'égalité de la collection).

notez que cela signifie le même collection, pas de collecte de l'élément en d'autres termes relatedPersons sur les deux person et anotherPerson doit être le même. Peut-être que vous réinitialisez cette collection après que les entités soient chargées? Ou vous avez initialisé les deux références avec la même instance de collecte?

53
répondu ChssPly76 2016-01-28 11:16:08

j'ai eu le même problème. Dans mon cas, le problème était que quelqu'un utilisait des balises pour copier les propriétés d'une entité à une autre, donc nous avons fini par avoir deux entités se référant à la même collection.

étant donné que j'ai passé un certain temps à étudier cette question, je recommande la liste de vérification suivante:

  • cherchez des scénarios comme entity1.setCollection(entity2.getCollection()) et getCollection renvoie la référence interne à la collection (si getCollection () renvoie une nouvelle instance du collection, alors vous n'avez pas besoin de s'inquiéter).

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

  • Rechercher BeanUtils.copyProperties(entity1, entity2).

41
répondu dgt 2015-05-21 19:53:58

Explication sur la pratique. Si vous essayez d'enregistrer 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 updated object à un objet parent:

message.setFiles(folders);

Simple d'enregistrer votre objet parent de la forme:

Set<Folder> folders = message.getFolders();
   folders.remove(inputFolder);
   folders.add(trashFolder);
   // Not set updated object here
MESSAGESDAO.getMessageDAO().save(message);
4
répondu Mirimas 2016-02-03 10:49:15

dans mon cas, je copiais et collais du code de mes autres classes, donc je n'ai pas remarqué que le code getter é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érences conceptoses mais si vous regardez à l'indique letrases

2
répondu John Lopez 2016-06-23 21:21:34

lire en ligne la cause de cette erreur peut être aussi un Hibernate bug, comme solution de contournement qu'il semble fonctionner, c'est de mettre un:

session.clear()

vous devez mettre le clair après avoir obtenu des données et avant de commit et 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 select to database, pour update ou insert Je ne sais pas si cette solution peut fonctionner ou causer des problèmes.

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

1
répondu Diego87 2016-08-10 15:56:37

moi aussi j'ai eu le même problème, quelqu'un a utilisé BeanUtils.copyProperties(source, target). Ici à la fois source et cible, utilisent la même collection que l'attribut.

alors j'ai utilisé la copie profonde comme ci-dessous..

comment cloner Collection en Java-copie profonde de ArrayList et HashSet

1
répondu raji 2018-04-22 00:44:15

j'ai fait face à une exception similaire dans ma demande. Après avoir regardé dans le stactrace il était clair que l'exception a été jeté dans un FlushEntityEventListener classe.

en hibernation 4.3.7 le MSLocalSessionFactory bean ne supporte plus le eventListeners propriété. Par conséquent, il faut explicitement récupérer le registre de service à partir de chaque session D'hibernation et ensuite définir les écouteurs d'événements personnalisés requis.

Dans le processus d'ajout d'événement personnalisé auditeurs, nous devons nous assurer que le correspondant les écouteurs d'événements par défaut sont supprimés de la session D'hibernation respective.

si l'écouteur d'événements par défaut n'est pas supprimé, alors le cas se présente de deux écouteurs d'événements enregistrés contre le même événement. Dans ce cas, tout en itérant au-dessus de ces auditeurs, contre les premiers auditeurs, toute collection dans la session sera signalée comme atteinte et pendant le traitement de la même collection contre le second auditeur lancerait cette exception D'hibernation.

Donc, assurez-vous que lorsque enregistrement des écouteurs personnalisés les écouteurs par défaut correspondants sont supprimés du registre.

0
répondu Dinesh Angolkar 2018-03-12 17:49:56

Envisager une entité:

public class Foo{
private<user> user;
/* with getters and setters */
}

Et envisager une Logique de classes:

class Foo1{
List<User> user = new ArrayList<>();
user = foo.getUser();
}

Voici l'utilisateur et foo.getUser() partager la même référence. Mais sauver les deux références crée un conflit.

L'utilisation correcte devrait être:

class Foo1 {
List<User> user = new ArrayList<>();
user.addAll(foo.getUser);
}

Cela évite le conflit.

-1
répondu Tarun 2018-04-22 01:50:38