Ответ 1
Я столкнулся с этой проблемой не так давно...
Я нашел эту статью: Производительность Antipatterns от одного до многих Ассоциация в Hibernate https://fedcsis.org/proceedings/2013/pliks/322.pdf
:
- Семантика пакета →
List
/Collection
+@OneToMany
→ Один элемент Добавлено: 1 удаление, N вставок, один элемент удален: 1 удаление, N вставок - Семантика списка →
List
+@OneToMany
+@IndexColumn
/@OrderColumn
→ Один элемент Добавлено: 1 вставка, обновления M, один элемент удален: 1 удаление, обновления M - Установить семантику →
Set
+@OneToMany
→ Один элемент Добавлено: 1 вставка, Один элемент удален: 1 удалить
Для меня: да, это означает, что вам нужно изменить List
на Set
для однонаправленного @OneToMany
. Поэтому я изменил свою модель, чтобы соответствовать ожиданиям Hibernate, и это вызывает множество проблем, потому что часть представления приложения полагалась на List
в основном...
В одной руке Set
является логическим выбором для меня, потому что нет дубликатов, с другой стороны List
было легче справиться.
Итак, JPA/Hibernate заставил меня изменить объект модели, и это было не в первый раз, когда вы используете @EmbededId
, вы делаете то, что вы, вероятно, не будете делать одинаково без JPA/Hibernate. И когда вам нужно знать HibernateProxy
во всем приложении, особенно в методах equals... else if(object instanceof HibernateProxy) {
..., вы заметили, что уровень persacency JPA/Hibernate немного навязчив в других слоях.
Но когда я использую напрямую JDBC, я также использую, чтобы изменить модель или методы бизнес-анализа, чтобы облегчить сохранение... Изоляция слоев может быть мечтой или стоить слишком много, чтобы сделать это на 100%?
И вы можете заказать Set
, если они SortedSet
как TreeSet
с аннотацией @OrderBy
Это создает проблему, когда какой-то код полагается на List
и не может быть изменен (например, компоненты JSF/PrimeFaces <dataTable>
или <repeat>
)
Поэтому вам нужно изменить свой Set
на List
и вернуться к Set
, но если вы сделаете setNotifications(new HashSet<>(notificationList))
, у вас появятся дополнительные запросы, потому что набор - это org.hibernate.collection.PersistentSet
, управляемый Hibernate... Поэтому я использовал addAll()
и removeAll()
вместо сеттеров:
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) ;
}
Обратите внимание на методы equals()
и hashCode()
вашего @Entity
...
Еще одна проблема заключается в том, что вам нужно освоить JPA и Hibernate, если вы хотите использовать JPA с Hibernate в качестве реализации, потому что семантика Set/List/Bag от Hibernate не от JPA (исправьте меня, если я ошибаюсь)
Спецификация предназначена для абстрагирования реализации, чтобы она не зависела от одного конкретного поставщика. Хотя большинство спецификаций JavaEE удалось, JPA не удалось для меня, и я отказался от независимости от Hibernate