it-roy-ru.com

Найдены общие ссылки на коллекцию org.hibernate.HibernateException

Я получил это сообщение об ошибке:

ошибка: найдены общие ссылки на коллекцию: Person.relatedPersons

Когда я попытался выполнить addToRelatedPersons(anotherPerson):

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

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

Мой домен:

Person {

 static hasMany = [relatedPersons:Person];

}

есть идеи, почему это происходит?

48
nightingale2k1

Hibernate показывает эту ошибку, когда вы пытаетесь сохранить несколько экземпляров сущности, совместно использующих same collection collection (т. Е. Идентичность коллекции в отличие от равенства коллекции).

Обратите внимание, что это означает, что один и тот же collection , а не элемент collection - другими словами, relatedPersons в person и anotherPerson должны быть одинаковыми. Возможно, вы сбрасываете эту коллекцию после загрузки сущностей? Или вы инициализировали обе ссылки одним экземпляром коллекции?

55
ChssPly76

У меня такая же проблема. В моем случае проблема заключалась в том, что кто-то использовал BeanUtils для копирования свойств одной сущности в другую, поэтому в итоге мы получили две сущности, ссылающиеся на одну и ту же коллекцию.

Учитывая, что я потратил некоторое время на изучение этой проблемы, я бы порекомендовал следующий контрольный список:

  • Ищите сценарии, такие как entity1.setCollection(entity2.getCollection()) и getCollection возвращает внутреннюю ссылку на коллекцию (если getCollection () возвращает новый экземпляр коллекции, вам не о чем беспокоиться).

  • Посмотрите, правильно ли реализована функция clone().

  • Ищите BeanUtils.copyProperties(entity1, entity2).

45
dgt

Пояснения на практике. Если вы попытаетесь сохранить свой объект, например:

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
Mirimas

Чтение в Интернете причины этой ошибки также может быть ошибкой hibernate, так как обходной путь, который, кажется, работает, должен поставить:

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

2
Diego87

В моем случае я копировал и вставлял код из других моих классов, поэтому я не заметил, что код геттера написан плохо:

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

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

Все ссылкиconceptosesно если вы посмотрите на get говоритletrases

2
John Lopez

Я тоже получил ту же проблему, кто-то использовал BeanUtils.copyProperties(source, target). Здесь и источник, и цель используют одну и ту же коллекцию как атрибут. 

Так что я просто использовал глубокую копию, как показано ниже ..

Как клонировать коллекцию в Java - Глубокая копия ArrayList и HashSet

1
raji

Я столкнулся с подобным исключением в моем приложении. После изучения трассировки стека стало ясно, что исключение было сгенерировано в классе FlushEntityEventListener.

В Hibernate 4.3.7 бин MSLocalSessionFactory больше не поддерживает свойство eventListeners. Следовательно, необходимо явно получить реестр служб из отдельных сеансовых компонентов Hibernate, а затем установить требуемые пользовательские прослушиватели событий.

В процессе добавления пользовательских прослушивателей событий мы должны убедиться, что соответствующие прослушиватели событий по умолчанию удалены из соответствующего сеанса Hibernate.

Если прослушиватель событий по умолчанию не удален, возникает случай, когда два прослушивателя событий регистрируются для одного и того же события. В этом случае при переборе этих прослушивателей для первых прослушивателей любые коллекции в сеансе будут помечены как достигнутые, а при обработке той же коллекции для второго прослушивателя возникнет это исключение Hibernate.

Поэтому убедитесь, что при регистрации пользовательских слушателей соответствующие слушатели по умолчанию удаляются из реестра.

0
Dinesh Angolkar