I have two entities: UserAccount and Notification. These have a relationship as shown below.
public class UserAccount {
@Id
@
I faced this problem not so long ago...
I found this article: Performance Antipatterns of One To Many Association in Hibernate https://fedcsis.org/proceedings/2013/pliks/322.pdf
in short:
List / Collection + @OneToMany -> One Element Added: 1 delete, N inserts , One Element Removed: 1 delete, N insertsList + @OneToMany + @IndexColumn / @OrderColumn -> One Element Added: 1 insert, M updates, One Element Removed: 1 delete, M updatesSet + @OneToMany -> One Element Added: 1 insert , One Element Removed: 1 deleteFor me: yes that mean that you have to change your List to Set for unidirectional @OneToMany. So I changed my model to match with Hibernate expectations and that cause a lot of issues because the view part of the application was relying on List mostly...
In one hand the Set is a logical choice for me because there are no duplications, in the other hand List were easier to deal with.
So JPA/Hibernate forced me to change the model object and that was not the first time, when you are using @EmbededId you do something that you probably won't do in the same way without JPA/Hibernate. And when you have to be aware of HibernateProxy in all the application especially in equals methods ... else if(object instanceof HibernateProxy) { ..., you notice the JPA/Hibernate persitence layer is a little bit intrusive in others layers.
But when I use directely JDBC I also use to change the model or the buisness methods to facilitate the persistence... Layers isolation is may be a dream or cost too much to be done at 100%?
And you can order a Set if they are SortedSet like TreeSet with the annotation @OrderBy
That bring a problem when some code rely on List and cannot be changed (such as JSF/PrimeFaces <dataTable> or <repeat> components)
So you have to change your Set into List and go back to Set but if you do setNotifications(new HashSet<>(notificationList)) you will have extra queries because the set is a org.hibernate.collection.PersistentSet managed by Hibernate... So I used addAll() and removeAll() instead of setters:
protected <E> void updateCollection(@NonNull Collection<E> oldCollection, @NonNull Collection<E> newCollection) {
Collection<E> toAdd = new ArrayList<>(newCollection) ;
toAdd.removeAll(oldCollection) ;
Collection<E> toRemove = new ArrayList<>(oldCollection) ;
toRemove.removeAll(newCollection) ;
oldCollection.removeAll(toRemove) ;
oldCollection.addAll(toAdd) ;
}
Mind the equals() and hashCode() methods of your @Entity...
One other problem is that you need to Master both JPA and Hibernate if you want to use JPA with Hibernate as the implementation because the Set/List/Bag semantic is from Hibernate not from JPA (correct me if I'm wrong)
A specification is made for abstracting the implementation to not depend on one specific vendor. Although most of JavaEE specs succed, JPA failed for me and I gave up to be independent of Hibernate
List: Allows duplicate elements in it.
Set: All elements should be unique.
Now, delete may be happening because you are over-writing element in list, and so when you modify persisted entity of UserAccount type, it is removing the entity which is in list previously.