2009-11-07 5 views
41

Я получил сообщение об ошибке:Найдено общие ссылки на коллекции org.hibernate.HibernateException

error: Found shared references to a collection: Person.relatedPersons

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

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

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

Мой домен:

Person { 

static hasMany = [relatedPersons:Person]; 

} 

любая идея, почему это происходит?

+1

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

+0

Я столкнулся с той же проблемой, что и @kaefert (т. Е. Одно и то же свойство более одного раза в пути наследования), но я получил исключение только тогда, когда одни и те же критерии выполнялись дважды (вызывая «list()» дважды). Tricky. –

ответ

49

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

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

+3

нашел проблему. Я сделал ошибку, набрав person.relatedPerson = anotherPerson; где-то в коде .... дох. – nightingale2k1

+0

@ nightingale2k1 как вы разрешаете это исключение – Mohamed

+0

да, но почему hibernate рассматривает это как проблему? Сущность имеет коллекцию, такую ​​как поле ManyToMany, и значение устанавливается путем поиска с другого объекта. – Tiina

36

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

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

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

  • Посмотрите, если clone() был выполнен правильно.

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

+0

Какой класс должен реализовывать клон()? – vacuum

+0

@ vacuum, модель домена. –

+0

Каким будет решение? – vashishth

4

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

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); 
2

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

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

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

Все ссылки conceptoses, но если вы посмотрите на ГЭТ говорит letrases

1

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

session.clear() 

Вы должны очистить после получения данных a Н.Д., прежде чем совершить и близко, смотри пример:

//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

1

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

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

http://javarevisited.blogspot.com/2014/03/how-to-clone-collection-in-java-deep-copy-vs-shallow.html

0

Позвольте мне объяснить это ясно, что эта ошибка,

Позвольте мне начать с примера,

рассмотреть предприятие

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

И consid er Business Logic class

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

Здесь пользователь и foo.getUser имеют общую ссылку. в то время как сохранение двух ссылок вызывает конфликт.

Правильное использование должно быть как:

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

Это позволяет избежать в конфликте

0

я столкнулся с аналогичным исключением в моем приложении. Изучив стек, было ясно, что исключение было выбрано в классе FlushEntityEventListener. В спящем режиме 4.3.7 MSLocalSessionFactory bean nomore поддерживает свойство eventListeners. Следовательно, нужно было явно получить реестр служб из отдельных сессионных компонентов hibernate, а затем установить необходимые пользовательские прослушиватели событий. В процессе добавления пользовательских прослушивателей событий мы должны убедиться, что соответствующие прослушиватели событий по умолчанию удалены из соответствующего сеанса спящего режима. Если прослушиватель событий по умолчанию не удаляется, возникает случай двух прослушивателей событий, зарегистрированных на одном событии. В этом случае при повторении этих слушателей против первых слушателей любые коллекции в сеансе будут отмечены как достигнутые, а при обработке одной и той же коллекции против второго слушателя будет выбрано это исключение спящего режима. Поэтому убедитесь, что при регистрации пользовательских прослушивателей соответствующие прослушиватели по умолчанию удаляются из реестра.

Смежные вопросы