Hibernate JPA
30 питань і відповідей у розділі Hibernate JPA.
Питання цього розділу
- Що таке проблема N+1 і як її вирішити
- У чому різниця між Lazy та Eager завантаженням
- Коли використовувати Lazy, а коли Eager loading
- Що таке LazyInitializationException і як її уникнути
- Які стратегії fetch існують в Hibernate
- Що робить анотація @BatchSize
- Опишіть життєвий цикл Entity в Hibernate
- Що таке стани transient, persistent, detached, removed
- Що таке кеш першого рівня в Hibernate
- Що таке кеш другого рівня і коли його використовувати
- Як налаштувати кеш другого рівня
- Що таке dirty checking в Hibernate
- Як працює механізм flush в Hibernate
- У чому різниця між persist() і merge()
- Що робить метод refresh()
- Що таке EntityManager і чим він відрізняється від Session
- Як реалізувати оптимістичне блокування в JPA
- Як реалізувати песимістичне блокування в JPA
- Що таке @Version і навіщо вона потрібна
- Як працюють каскадні операції (Cascade)
- Які типи Cascade існують
- Що таке orphan removal
- Як правильно використовувати @OneToMany і @ManyToOne
- У чому особливості bidirectional relationships
- Як уникнути нескінченної рекурсії при серіалізації Entity
- Що таке JPQL і чим він відрізняється від SQL
- Що таке Criteria API і коли його використовувати
- Як використовувати JOIN FETCH для вирішення проблеми N+1
- Що таке projection в JPA
- Які типи наслідування підтримує JPA
Навігатор по розділу
30 запитань для підготовки до співбесіди на Middle Java Developer.
📋 Всі запитання
🗺️ Карта залежностей тем
┌──────────────────────────────────────────┐
│ FETCH І N+1 (1-6) │
│ 1. N+1 проблема │
│ 2. Lazy vs Eager │
│ 3. Коли що обрати │
│ 4. LazyInitializationException │
│ 5. Fetch стратегії │
│ 6. @BatchSize │
└──────────────────┬───────────────────────┘
│
┌──────────────────────────┼──────────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌────────────────────┐
│ ENTITY │ │ CACHING │ │ LOCKING │
│ LIFECYCLE │ │ (9-13) │ │ (17-19) │
│ (7-8, 12-16) │ │ 9. L1 cache │ │ 17. Optimistic │
│ 7. Lifecycle │ │ 10. L2 cache │ │ 18. Pessimistic │
│ 8. Stani │ │ 11. L2 налашт.│ │ 19. @Version │
│ 12. Dirty chk │ │ 12. Dirty chk │ │ │
│ 13. Flush │ │ 13. Flush │ │ │
│ 14. persist/ │ │ │ │ │
│ merge │ │ │ │ │
│ 15. refresh │ │ │ │ │
│ 16. EM vs Sess │ │ │ │ │
└───────┬───────┘ └───────┬───────┘ └────────┬───────────┘
│ │ │
└────────────────────────┼────────────────────────┘
▼
┌──────────────────────────────────────────┐
│ RELATIONSHIPS (20-25) │
│ 20. Cascade огляд │
│ 21. Cascade типи │
│ 22. Orphan removal │
│ 23. @OneToMany/@ManyToOne │
│ 24. Bidirectional │
│ 25. Серіалізація рекурсії │
└──────────────────────────────────────────┘
│
┌────────────────────────┼────────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌────────────────────┐
│ QUERY LANG │ │ N+1 РІШЕННЯ │ │ НАСЛІДУВАННЯ │
│ (26-27) │ │ (28-29) │ │ (30) │
│ 26. JPQL vs │ │ 28. JOIN FETCH │ │ 30. Inheritance │
│ SQL │ │ 29. Projection │ │ types │
│ 27. Criteria │ │ │ │ │
│ API │ │ │ │ │
└───────────────┘ └───────────────┘ └────────────────────┘
🎯 Рекомендований порядок вивчення
🟢 Рівень Junior (тижні 1-2)
| Крок | Тема | Файли | Мета |
|---|---|---|---|
| 1 | Стани Entity | Q7, Q8 | Transient, Persistent, Detached, Removed |
| 2 | Lazy vs Eager | Q2, Q3 | Коли що використовувати |
| 3 | persist vs merge | Q14 | Який метод для якого стану |
| 4 | Cascade база | Q20, Q21 | Що таке cascade, які типи |
| 5 | JPQL vs SQL | Q26 | Чим відрізняється, коли що |
🟡 Рівень Middle (тижні 3-4)
| Крок | Тема | Файли | Мета |
|---|---|---|---|
| 1 | N+1 проблема | Q1, Q28 | Чому виникає, JOIN FETCH рішення |
| 2 | LazyInitializationException | Q4 | Чому виникає, 3 рішення |
| 3 | Dirty checking | Q12, Q13 | Як працює, коли flush |
| 4 | L1 cache | Q9 | Identity guarantee, snapshot |
| 5 | @OneToMany/@ManyToOne | Q23, Q24 | mappedBy, owner/inverse, helper methods |
| 6 | Оптимістичне блокування | Q17, Q19 | @Version, OptimisticLockException |
| 7 | Projection | Q29 | Навіщо, interface-based, class-based |
🔴 Рівень Senior (тижні 5-6)
| Крок | Тема | Файли | Мета |
|---|---|---|---|
| 1 | L2 cache | Q10, Q11 | Concurrency strategies, clustering, invalidation |
| 2 | Pessimistic locking | Q18 | PESSIMISTIC_READ/WRITE/NONE, NOWAIT, SKIP LOCKED |
| 3 | Fetch strategies deep | Q5, Q6 | FetchMode vs FetchType, SUBSELECT vs BATCH |
| 4 | EntityManager vs Session | Q16 | Internal implementation, Jakarta vs javax |
| 5 | Circular cascade | Q20, Q22 | Cycle detection, orphanRemoval vs REMOVE |
| 6 | Criteria API | Q27 | Type-safe, Metamodel, dynamic queries |
| 7 | Inheritance | Q30 | SINGLE_TABLE vs JOINED vs TABLE_PER_CLASS trade-offs |
| 8 | Serialization | Q25 | Jackson annotations, LazyInitializationException in REST |
🔗 Ключові зв’язки між темами
Тема: Fetch та N+1
Q2 (Lazy vs Eager) → Q3 (Коли що) → Q4 (LazyInitException)
↓
Q5 (Fetch стратегії) → Q6 (@BatchSize) → Q1 (N+1) → Q28 (JOIN FETCH)
Ключові зв’язки:
- Q2 ↔ Q5: FetchType (коли) vs FetchMode (як)
- Q4 ↔ Q28: JOIN FETCH запобігає LazyInitializationException
- Q5 ↔ Q6: @BatchSize — окремий механізм від FetchMode
- Q1 ↔ Q29: Projection теж вирішує N+1 (завантажує тільки потрібні колонки)
Тема: Entity Lifecycle
Q7 (Lifecycle) → Q8 (Стани) → Q14 (persist/merge)
↓ ↓
Q12 (Dirty check) → Q13 (Flush) → Q15 (refresh)
↓
Q16 (EntityManager vs Session)
Ключові зв’язки:
- Q8 ↔ Q14: persist() для transient, merge() для detached
- Q12 ↔ Q13: Dirty checking тригерить flush при commit/перед запитом
- Q15 ↔ Q8: refresh() переводить detached назад в persistent
Тема: Caching
Q9 (L1 cache) → Q10 (L2 cache) → Q11 (L2 налаштування)
Ключові зв’язки:
- Q9 ↔ Q12: L1 cache зберігає snapshot для dirty checking
- Q10 ↔ Q11: Конфігурація провайдера, clustering, invalidation
Тема: Relationships
Q20 (Cascade) → Q21 (Cascade типи) → Q22 (Orphan removal)
↓
Q23 (@OneToMany/@ManyToOne) → Q24 (Bidirectional) → Q25 (Серіалізація)
Ключові зв’язки:
- Q21 ↔ Q22: CascadeType.REMOVE vs orphanRemoval
- Q23 ↔ Q24: Bidirectional вимагає синхронізації обох сторін
- Q24 ↔ Q25: Bidirectional → нескінченна рекурсія при серіалізації
- Q25 ↔ Q4: LazyInitializationException при серіалізації LAZY полів
Тема: Query та Inheritance
Q26 (JPQL) → Q27 (Criteria API) → Q28 (JOIN FETCH) → Q29 (Projection)
↓
Q30 (Inheritance)
Ключові зв’язки:
- Q26 ↔ Q27: JPQL — рядковий, Criteria — type-safe
- Q28 ↔ Q1: JOIN FETCH — головне рішення N+1
- Q29 ↔ Q26: Projection в JPQL через constructor expression
- Q30 ↔ Q26: Поліморфні запити залежать від стратегії наслідування
🎓 Шпаргалка: що знати для кожного рівня
🟢 Junior
- Стани Entity: transient (new), persistent (managed), detached (session closed), removed
- Lazy = завантаження при зверненні, Eager = одразу. LAZY за замовчуванням для колекцій
- persist() = INSERT для transient, merge() = SELECT+UPDATE для detached
- Cascade = автоматичне поширення операцій на пов’язані сутності
- JPQL працює з entity, SQL — з таблицями
🟡 Middle
- N+1: 1 запит на батька + N на дочірні. Рішення: JOIN FETCH, @BatchSize, EntityGraph
- Dirty checking: Hibernate зберігає snapshot, при flush порівнює → UPDATE якщо змінилось
- L1 cache: на рівні EntityManager, identity guarantee, snapshot для dirty checking
- @Version: optimistic locking, version=0 при INSERT, +1 при кожному UPDATE
- orphanRemoval: видаляє дитину при видаленні з колекції, CascadeType.REMOVE — лише при видаленні батька
- Bidirectional: mappedBy на inverse side, helper methods для синхронізації
🔴 Senior
- L2 cache: на рівні EntityManagerFactory, clustering (Hazelcast, Infinispan), eventual consistency
- Pessimistic locking: PESSIMISTIC_READ (shared), PESSIMISTIC_WRITE (exclusive), NOWAIT, SKIP LOCKED
- FetchMode JOIN ігнорує LAZY в Hibernate 5.x. SUBSELECT тільки якщо батьки завантажені одним запитом
- Flush order: INSERT → UPDATE → DELETE (критично для FK constraints)
- Cartesian product при кількох JOIN FETCH — Hibernate 6 не вирішив повністю
- @MappedSuperclass ≠ @Entity: немає таблиці, не можна query, поліморфні запити не працюють
- Jackson @JsonManagedReference/@JsonBackReference — не JPA, serializer-specific
📝 Формат кожного файлу
Кожен файл містить:
- 🟢 Junior Level — базове розуміння, прості аналогії, приклади
- 🟡 Middle Level — внутрішності, типові помилки, практичні приклади
- 🔴 Senior Level — deep dive, edge cases, production experience, monitoring
- 🎯 Шпаргалка для співбесіди — ключові тези, часті запитання, червоні прапорці, пов’язані теми