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 ?
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?
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())
etgetCollection
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)
.
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);
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
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
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
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.
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.