diff --git a/dev/java/hibernate/Дублирование значений при использовании @ElementCollection и @OneToMany.md b/dev/java/hibernate/Дублирование значений при использовании @ElementCollection и @OneToMany.md
new file mode 100644
index 00000000..7eb6924c
--- /dev/null
+++ b/dev/java/hibernate/Дублирование значений при использовании @ElementCollection и @OneToMany.md
@@ -0,0 +1,48 @@
+---
+aliases:
+tags:
+ - maturity/🌱
+date:
+ - - 2024-09-06
+zero-link:
+ - "[[../../../meta/zero/00 Hibernate|00 Hibernate]]"
+parents:
+linked:
+---
+Столкнулся с неочевидным поведением `@ElementCollection` в связке с `@OneToMany`. Может случиться так, что в `@OneToMany` будет дублирование значений из-за `@ElementCollection`. Проще объяснить на примере.
+
+Допустим у нас есть три таблицы: `user`, `user_nickname`, `address`. Есть сущность `User`:
+
+```java
+@Entity
+public class User {
+
+ // ... ... ... ... ...
+
+ @OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
+ private List
stages = new ArrayList<>();
+
+ @ElementCollection(fetch = FetchType.EAGER)
+ @CollectionTable(
+ name = "user_nickname",
+ joinColumns = @JoinColumn(name = "user_id")
+ )
+ @Column(name = "nickname")
+ private Set nicknames = new HashSet<>();
+
+ // ... ... ... ... ...
+
+}
+```
+
+Допустим у нас одна запись про пользователя, у которого есть три адреса и один никнейм. В этом случае все хорошо, все придет корректно.
+
+==Добавим этому пользователю еще один никнейм. Теперь мы получаем шесть адресов и два никнейма. Откуда взялись еще три лишних адреса, в базе данных их все еще три.== Это дубликаты. При этом, если вы воспользуетесь пагинацией JPA, то дублей уже не будет. It is magic 💫
+
+Магии в программировании, как вы понимаете, нет. Они создаются при использовании `FetchType.EAGER` у `@OneToMany` в совокупности с `@ElementCollection(fetch = FetchType.EAGER)`. Hibernate генерирует запрос с двумя-тремя полными соединениями, отсюда и берутся дубли. При этом в пагинации Hibernate не генерирует джойны, а использует кучу селектов, отсюда и отсутствие дублей при пагинации.
+
+Эта проблема решается несколькими способами:
+
+- Переделайте `List` в `Set` у `@OneToMany`.
+- Уберите `FetchType.EAGER` у `@OneToMany`.
+- Добавьте `@Fetch(FetchMode.SUBSELECT)` у `@OneToMany`. это аннотация Hibernate, которая вместо JOIN использует подзапрос. О [подзапросах я писал в отдельной статье](https://struchkov.dev/blog/ru/select-subquery).
\ No newline at end of file
diff --git a/meta/zero/00 Hibernate.md b/meta/zero/00 Hibernate.md
index 2c0145ed..689f67d0 100644
--- a/meta/zero/00 Hibernate.md
+++ b/meta/zero/00 Hibernate.md
@@ -5,5 +5,5 @@ tags:
- type/zero-link
title: Hibernate
---
-- [Дублирование значений при использовании @ElementCollection и @OneToMany](../../../../_inbox/Дублирование%20значений%20при%20использовании%20@ElementCollection%20и%20@OneToMany.md)
+- [Дублирование значений при использовании @ElementCollection и @OneToMany](../../dev/java/hibernate/Дублирование%20значений%20при%20использовании%20@ElementCollection%20и%20@OneToMany.md)
- [Логирование SQL в Hibernate](../../dev/java/hibernate/Логирование%20SQL%20в%20Hibernate.md)
\ No newline at end of file