Найдено общие ссылки на коллекцию org.hibernate.HibernateException
Я получил это сообщение об ошибке:
error: найдены общие ссылки на коллекцию: Person.relatedPersons
Когда я попытался выполнить addToRelatedPersons(anotherPerson)
:
person.addToRelatedPersons(anotherPerson);
anotherPerson.addToRelatedPersons(person);
anotherPerson.save();
person.save();
Мой домен:
Person {
static hasMany = [relatedPersons:Person];
}
любая идея, почему это происходит?
Ответы
Ответ 1
Hibernate показывает эту ошибку, когда вы пытаетесь сохранить более одного экземпляра сущности, совместно использующего ссылку same для коллекции (т.е. идентификатор коллекции в отличие от равенства коллекции).
Обратите внимание, что это означает, что те же коллекция, а не элемент коллекции - другими словами relatedPersons
на person
и anotherPerson
должны быть одинаковыми. Возможно, вы сбросите эту коллекцию после загрузки объектов? Или вы инициализировали обе ссылки с одним экземпляром коллекции?
Ответ 2
У меня была та же проблема. В моем случае проблема заключалась в том, что кто-то использовал BeanUtils для копирования свойств одного объекта в другой, поэтому мы получили два объекта, ссылающихся на одну и ту же коллекцию.
Учитывая, что я потратил некоторое время на изучение этой проблемы, я бы рекомендовал следующий контрольный список:
-
Поиск сценариев, таких как entity1.setCollection(entity2.getCollection())
и getCollection
, возвращает внутреннюю ссылку на коллекцию (если getCollection() возвращает новый экземпляр коллекции, тогда вам не нужно беспокоиться).
-
Посмотрите, правильно ли реализована функция clone()
.
-
Найдите BeanUtils.copyProperties(entity1, entity2)
.
Ответ 3
Объяснение практики. Если вы попытаетесь сохранить свой объект, например:
Set<Folder> folders = message.getFolders();
folders.remove(inputFolder);
folders.add(trashFolder);
message.setFiles(folders);
MESSAGESDAO.getMessageDAO().save(message);
вам не нужно устанавливать обновленный объект в родительский объект:
message.setFiles(folders);
Просто сохраните свой родительский объект, например:
Set<Folder> folders = message.getFolders();
folders.remove(inputFolder);
folders.add(trashFolder);
// Not set updated object here
MESSAGESDAO.getMessageDAO().save(message);
Ответ 4
В моем случае я копировал и вставлял код из других классов, поэтому я не заметил, что код получателя был написан плохо:
@OneToMany(fetch = FetchType.LAZY, mappedBy = "credito")
public Set getConceptoses() {
return this.letrases;
}
public void setConceptoses(Set conceptoses) {
this.conceptoses = conceptoses;
}
Все ссылки концепций, но если вы посмотрите на get, напишите letrases
Ответ 5
Чтение в Интернете причины этой ошибки также может быть ошибкой спящего режима, как обходной путь, который, по-видимому, работает, нужно поставить a:
session.clear()
Вы должны очистить после получения данных и до фиксации и закрытия, см. пример:
//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;
Я использую это решение для выбора базы данных, для обновления или вставки я не знаю, может ли это решение работать или может вызвать проблемы.
Моя проблема равна 100% от этого: http://www.progtown.com/topic128073-hibernate-many-to-many-on-two-tables.html
Ответ 6
У меня тоже такая же проблема, кто-то использовал BeanUtils.copyProperties(источник, цель). Здесь и источник, и цель, используют ту же коллекцию, что и атрибут.
Итак, я просто использовал глубокую копию, как показано ниже.
http://javarevisited.blogspot.com/2014/03/how-to-clone-collection-in-java-deep-copy-vs-shallow.html
Ответ 7
Позвольте мне ясно объяснить, что это за ошибка,
Позвольте мне начать с примера,
рассмотреть объект
public class foo{
private<user> user;
/* with getters and setters */
}
И рассмотрим класс бизнес-логики
class foo1{
.
.
List<User> user = new ArrayList<>();
user = foo.getUser();
.
.
}
Здесь пользователь и foo.getUser используют одну и ту же ссылку. при сохранении двух ссылок возникает конфликт.
Правильное использование должно выглядеть следующим образом:
class foo1 {
.
.
List<User> user = new ArrayList<>();
user.addAll(foo.getUser);
.
.
}
Это позволяет избежать конфликта