Found shared references to a collection org.hibernate.HibernateException
Solution 1
Hibernate shows this error when you attempt to persist more than one entity instance sharing the same collection reference (i.e. the collection identity in contrast with collection equality).
Note that it means the same collection, not collection element - in other words relatedPersons
on both person
and anotherPerson
must be the same. Perhaps you're resetting that collection after entities are loaded? Or you've initialized both references with the same collection instance?
Solution 2
I had the same problem. In my case, the issue was that someone used BeanUtils to copy the properties of one entity to another, so we ended up having two entities referencing the same collection.
Given that I spent some time investigating this issue, I would recommend the following checklist:
Look for scenarios like
entity1.setCollection(entity2.getCollection())
andgetCollection
returns the internal reference to the collection (if getCollection() returns a new instance of the collection, then you don't need to worry).Look if
clone()
has been implemented correctly.Look for
BeanUtils.copyProperties(entity1, entity2)
.
Solution 3
Explanation on practice. If you try to save your object, e.g.:
Set<Folder> folders = message.getFolders();
folders.remove(inputFolder);
folders.add(trashFolder);
message.setFiles(folders);
MESSAGESDAO.getMessageDAO().save(message);
you don't need to set updated object to a parent object:
message.setFiles(folders);
Simple save your parent object like:
Set<Folder> folders = message.getFolders();
folders.remove(inputFolder);
folders.add(trashFolder);
// Not set updated object here
MESSAGESDAO.getMessageDAO().save(message);
Solution 4
I have experienced a great example of reproducing such a problem. Maybe my experience will help someone one day.
Short version
Check that your @Embedded Id of container has no possible collisions.
Long version
When Hibernate instantiates collection wrapper, it searches for already instantiated collection by CollectionKey in internal Map.
For Entity with @Embedded id, CollectionKey wraps EmbeddedComponentType and uses @Embedded Id properties for equality checks and hashCode calculation.
So if you have two entities with equal @Embedded Ids, Hibernate will instantiate and put new collection by the first key and will find same collection for the second key. So two entities with same @Embedded Id will be populated with same collection.
Example
Suppose you have Account entity which has lazy set of loans. And Account has @Embedded Id consists of several parts(columns).
@Entity
@Table(schema = "SOME", name = "ACCOUNT")
public class Account {
@OneToMany(fetch = FetchType.LAZY, mappedBy = "account")
private Set<Loan> loans;
@Embedded
private AccountId accountId;
...
}
@Embeddable
public class AccountId {
@Column(name = "X")
private Long x;
@Column(name = "BRANCH")
private String branchId;
@Column(name = "Z")
private String z;
...
}
Then suppose that Account has additional property mapped by @Embedded Id but has relation to other entity Branch.
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "BRANCH")
@MapsId("accountId.branchId")
@NotFound(action = NotFoundAction.IGNORE)//Look at this!
private Branch branch;
It could happen that you have no FK for Account to Brunch relation id DB so Account.BRANCH column can have any value not presented in Branch table.
According to @NotFound(action = NotFoundAction.IGNORE)
if value is not present in related table, Hibernate will load null value for the property.
If X and Y columns of two Accounts are same(which is fine), but BRANCH is different and not presented in Branch table, hibernate will load null for both and Embedded Ids will be equal.
So two CollectionKey objects will be equal and will have same hashCode for different Accounts.
result = {CollectionKey@34809} "CollectionKey[Account.loans#Account@43deab74]"
role = "Account.loans"
key = {Account@26451}
keyType = {EmbeddedComponentType@21355}
factory = {SessionFactoryImpl@21356}
hashCode = 1187125168
entityMode = {EntityMode@17415} "pojo"
result = {CollectionKey@35653} "CollectionKey[Account.loans#Account@33470aa]"
role = "Account.loans"
key = {Account@35225}
keyType = {EmbeddedComponentType@21355}
factory = {SessionFactoryImpl@21356}
hashCode = 1187125168
entityMode = {EntityMode@17415} "pojo"
Because of this, Hibernate will load same PesistentSet for two entities.
Solution 5
Reading online the cause of this error can be also an hibernate bug, as workaround that it seems to work, it is to put a:
session.clear()
You must to put the clear after getting data and before commit and close, see example:
//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;
I use this solution for select to database, for update or insert i don't know if this solution can work or can cause problems.
My problem is equal at 100% of this: http://www.progtown.com/topic128073-hibernate-many-to-many-on-two-tables.html
nightingale2k1
---- Grails and PHP programmer --- love doing web jobs
Updated on July 05, 2022Comments
-
nightingale2k1 almost 2 years
I got this error message:
error: Found shared references to a collection: Person.relatedPersons
When I tried to execute
addToRelatedPersons(anotherPerson)
:person.addToRelatedPersons(anotherPerson); anotherPerson.addToRelatedPersons(person); anotherPerson.save(); person.save();
My domain:
Person { static hasMany = [relatedPersons:Person]; }
any idea why this happens ?
-
nightingale2k1 over 14 yearsfound the problem. I did a mistake by typing person.relatedPerson = anotherPerson ; somewhere in the code .... doh.
-
vacuum over 11 yearswhat class should implement clone() ?
-
Rubens Mariuzzo almost 9 years@vacuum, the domain model.
-
vashishth almost 8 yearswhat would be the solution here?
-
Tiina over 6 yearsyes, but why hibernate treats this as a problem? An entity has a collection like a ManyToMany field, and the value is set by looking up from another entity.
-
Bhushan about 6 years@vashishth Earlier, I was doing
entity1.setCollection(entity2.getCollection())
. I solved it byentity1.setCollection(new HashSet(entity2.getCollection()))
-
Kalle Richter about 6 yearsThis is unnecessarily hard to read because class names are lower case and the code contains unnecessary assignments.
-
gtiwari333 almost 6 yearsThanks for the checklist. In my case I was doing
BeanUtils.copyProperties(oldRec, newRec)
in 'clone()` method. I updated theBeanUtils.copyProperties
to skip the newly addedManyToMany
field asBeanUtils.copyProperties(oldRec, newRec, newCollectionField)
. -
ichalos over 4 yearsI am sorry, but this is not really helpful as it's just a simple mistake on your side.
-
Fildor almost 4 yearsCould you please edit to make this a little more readable?
-
Artiow over 2 yearsYou saved my day. I had the same issue, but because of non-unique composite key for many-to-many relation. Thanks a lot! Where can I read about this Hibernate feature?
-
GreenROBO over 2 years@Bhushan - Got helped from your comment. Thanks