# Why do Hibernate remove all elements in set, if i remove all elements of another set in the same class?

**URL:** <https://discourse.hibernate.org/t/why-do-hibernate-remove-all-elements-in-set-if-i-remove-all-elements-of-another-set-in-the-same-class/1407>\
**Category:** Hibernate ORM\
**Created:** [September 18, 2018, 10:15am UTC](https://discourse.hibernate.org/t/why-do-hibernate-remove-all-elements-in-set-if-i-remove-all-elements-of-another-set-in-the-same-class/1407 "2018-09-18T10:15:54Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Rizgar](https://avatars.discourse-cdn.com/v4/letter/r/7feea3/32.png) [@Rizgar](https://discourse.hibernate.org/u/Rizgar)\
**Post date:** [September 18, 2018, 10:15am UTC](https://discourse.hibernate.org/t/why-do-hibernate-remove-all-elements-in-set-if-i-remove-all-elements-of-another-set-in-the-same-class/1407/1 "2018-09-18T10:15:54Z")

</div>

I have two classes: Book and Member. In Member class, there is two HashSet which stores Books: borrowedBooks and returnedBooks. If i want to remove one Book from borrowedBooks and put it in returnedBook, will Hibernate do that without problem till the last element in borrowedBooks. But if i remove the last element in borrowedBooks, than remove Hibernate also all of the Books in returnedBook. So, at the end of scenario there is no more Book in borrowedBooks but also in returnedBooks… Like that:

a) borrowedBooks: a, b, c

a) returnedBooks:

* * *

b) borrowedBooks: a, b

b) returnedBooks: c

* * *

c) borrowedBooks: a

c) returnedBooks: b, c

* * *

d) borrowedBooks: -

d) returnedBooks: -

* * *

Thats really not understandable! Thanks a lot for your helps! Here are my classes:

```auto
@Entity public class Book {

@Id
@TableGenerator(...)
@GeneratedValue(generator = "Member_Id")
private long barcode;
private long isbn=0;
private String bookTitle="";
// some other fields

getters / setters

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + (int) (barcode ^ (barcode >>> 32));
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Book other = (Book) obj;
    if (barcode != other.barcode)
        return false;
    return true;
}
}

```

```auto
@Entity public class Member {

@Id
@TableGenerator(...)
@GeneratedValue(generator = "Book_Barcode")
private int id;

@OneToMany(fetch = FetchType.EAGER)
private Set<Book> returnedBooks = new HashSet<>();

@OneToMany(fetch = FetchType.EAGER)
private Set<Book> borrowedBooks = new HashSet<>();

@OneToMany(fetch = FetchType.EAGER)
private Set<Book> renewedBooks = new HashSet<>();
}

```

```auto
@Repository public class MemberDAOImpl implements MemberDAO {

@Autowired
private SessionFactory sessionFactory;

@Override
@Transactional
public void borrowBook(Member member, Book book) {
    if (book.getStatus().equals("Available") && 
        book.getAvailableAmount() > 0) {

        Session currentSession = sessionFactory.getCurrentSession();

        book.setBorrowedDate(new Date());
        book.setAvailableAmount(book.getAvailableAmount() - 1);
        book.setStatus("Borrowed");
        currentSession.update(book);

        Member newMember = currentSession.find(Member.class, member.getId());
        newMember.getBorrowedBooks().add(book);
        currentSession.update(newMember);
    } 
}

@Override
@Transactional
public void returnBook(Member member, Book book) {
    if (book.getStatus().equals("Borrowed")) {

        Session currentSession = sessionFactory.getCurrentSession();

        Member newMember = currentSession.find(Member.class, member.getId());
        newMember.getReturnedBooks().add(book);
        newMember.getBorrowedBooks().remove(book);
        currentSession.update(newMember);

        book.setBorrowedDate(null);
        book.setAvailableAmount(book.getAvailableAmount() + 1);
        book.setStatus("Available");
        book.setRenewedTimes(0);
        currentSession.update(book);
    } 
}
}

```

So, there is no problem in public void borrowBook(…)  
There is something wrong in public void returnBook(…)!!!  
I spent a lot of time, but i did find any way… Thanks in advance!

---

<div class="post-metadata">

**Author:** ![vlad](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/vlad/32/658_2.png) [@vlad](https://discourse.hibernate.org/u/vlad)\
**Post date:** [September 18, 2018, 1:00pm UTC](https://discourse.hibernate.org/t/why-do-hibernate-remove-all-elements-in-set-if-i-remove-all-elements-of-another-set-in-the-same-class/1407/2 "2018-09-18T13:00:04Z")

</div>

There are many things that are wrong in your code, which could have been easily prevented by reading the [Hibernate User Guide](http://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html).

Using [EAGER fetching is a bad idea](https://vladmihalcea.com/eager-fetching-is-a-code-smell/) anyway, but using it for 3 collections is going to generate a huge Cartesian Product which is going to cause a significant performance issue.

```auto
@OneToMany(fetch = FetchType.EAGER)
private Set<Book> returnedBooks = new HashSet<>();

@OneToMany(fetch = FetchType.EAGER)
private Set<Book> borrowedBooks = new HashSet<>();

@OneToMany(fetch = FetchType.EAGER)
private Set<Book> renewedBooks = new HashSet<>();

```

You’re using primitive-based identifiers:

`private long barcode;`

You’re using the TABLE generator which is also the [worst identifier generator](https://vladmihalcea.com/why-you-should-never-use-the-table-identifier-generator-with-jpa-and-hibernate/) to choose from.

Your `hashCode` relies on the identifier which might change after the entities get persisted. Check out [this article for more details](https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/) about how to write equals and hashCode when using the entity identifier only.

This line:

```
currentSession.update(newMember);

```

is useless. The `Session#update` is not for updating a managed entity. It’s for scheduling an update for detached one. You can remove it and HIbernate will still update the `newMember` since it’s a manged entity.

This one:

```
currentSession.update(book);

```

might be replaced with `merge` which is safer if the entity is already attached to the current running Session.

> So, there is no problem in public void borrowBook(…)  
> There is something wrong in public void returnBook(…)!!!

Did you write a unit test to validate the logic? After you add the unit test, you have to post it in your question as well.

---

<div class="post-metadata">

**Author:** ![Rizgar](https://avatars.discourse-cdn.com/v4/letter/r/7feea3/32.png) [@Rizgar](https://discourse.hibernate.org/u/Rizgar)\
**Post date:** [September 18, 2018, 1:39pm UTC](https://discourse.hibernate.org/t/why-do-hibernate-remove-all-elements-in-set-if-i-remove-all-elements-of-another-set-in-the-same-class/1407/3 "2018-09-18T13:39:28Z")

</div>

Thanks for your suggestions!  
I did not know that TABLE generator is not good and also about “update”.  
I know that EAGER fetching is not good, but it’s not that important right now. There is another big problem which i can not solve for 2 days. I didn’t right any unit test, but i tested it myself.

borrowBook method does everything i want. But in method “returnBook()” when the last element in set “borrowBook” is deleted, all elements in set “returnBook” deleted also.  
hashCode will not change, because the barcode (which is ID) will not change.

---

<div class="post-metadata">

**Author:** ![vlad](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.hibernate.org/vlad/32/658_2.png) [@vlad](https://discourse.hibernate.org/u/vlad)\
**Post date:** [September 18, 2018, 1:42pm UTC](https://discourse.hibernate.org/t/why-do-hibernate-remove-all-elements-in-set-if-i-remove-all-elements-of-another-set-in-the-same-class/1407/4 "2018-09-18T13:42:18Z")

</div>

> [@Rizgar](#):
>
> I didn’t right any unit test, but i tested it myself.

That’s how many problems start. You need to write the unit test now, and after you’re done, you will have to add it here along with the SQL statements executed by Hibernate, so we get a better understanding of what happens behind the scenes.
