2

I know this question is asked and answered a number of times and also has a workaround

like in Found shared references to a collection org.hibernate.HibernateException http://www.java2s.com/Questions_And_Answers/JPA/Collection/HibernateException.htm

but none of the above worked for me.

I am using SpringBoot, JPA, Hibernate and have mapping as provided below.

I am retrieving the list of Phone and iterating over it using for loop. I am getting the error Found shared references to a collection: Phone.person while iterating over phone list

org.hibernate.HibernateException: Found shared references to a collection: Phone.person
    at org.hibernate.engine.internal.Collections.processReachableCollection(Collections.java:188) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.FlushVisitor.processCollection(FlushVisitor.java:50) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:104) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:65) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:59) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:182) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:232) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:92) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]

Mapping to Phone entity

@Entity
@Table(name = "PHONETABLE")
@Data
public class Phone{

// other column mapping

    @ManyToMany
    @JoinTable(name = "SomeTable", joinColumns = {
            @JoinColumn(name = "column1", referencedColumnName = "personColumn") }, inverseJoinColumns = {
                    @JoinColumn(name = "id", referencedColumnName = "id", unique = true) })
    @JsonIgnore
    private Set<Person> person;

}

I am calling the findByIdMethod to fetch the data from the repository. I have used lombok for getters are setters.

If anyone knows the solution then it would be great. Thanks;

SSK
  • 3,444
  • 6
  • 32
  • 59

1 Answers1

3

It appears that you have multiple Phone instances with the same Set instance for person. This can happen when you clone or copy a Phone, or do something like phone1.setPerson(phone2.getPerson()).

It's okay for the Persons to be the same, but not the Set itself. Each phone should create a new instance of a Set that is only used within the entity.

You can make sure of this, by instantiating collections in the constructor or directly after declaration and then never calling the setter for the collection, e.g.

private Set<Person> person = new HashSet<Person>();

void addPerson(Person person) {
    this.person.add(person);
}

and only use addPerson, never setPerson (you can add similar helper methods to add multiple persons, or remove a person, etc.).

You can also return a copy of the set instead of the set itself in the getPerson getter to be sure that the collection instance never leaks out.

Dario Seidl
  • 4,140
  • 1
  • 39
  • 55
  • Hi Dario Seidl, Thanks for your time I have used *@Data from lombok* Not sure how we can skip the setter in this case. I have tried your solution but it not worked as expected – SSK Apr 07 '20 at 10:55
  • I am calling the *findByIdMethod* to fetch the data from the repository. I have used lombok for getters are setters. – SSK Apr 08 '20 at 03:42
  • OK, having a setter and getter generated by Lombok is not a problem in itself. You just need to make sure that you are not setting the collection of one entity to one of another. You can still modify the visibility of the setter when you use `@Data` if you want: https://projectlombok.org/features/Data – Dario Seidl Apr 08 '20 at 11:02