1) Що таке репозиторій (Repository) простими словами
Repository — це компонент, який “вміє” працювати з таблицею в базі даних: зберігати, читати, оновлювати і видаляти записи.
Уяви це як “пульт керування таблицею”:
- натиснув save() → запис зберігся в БД
- натиснув findAll() → отримав всі записи
- натиснув findById() → отримав конкретний рядок
- натиснув deleteById() → видалив запис
Головна ідея: у коді ми не пишемо SQL “руками”. Ми працюємо методами Java, а Spring Data JPA перетворює це на SQL.
2) Що ми зробили конкретно тут
Ми створили інтерфейс:
Тобто ми сказали Spring:
- цей репозиторій працює з сутністю User;
- тип ID у цієї сутності — Long;
- і ми хочемо отримати всі CRUD-методи, які вже є у JpaRepository.
3) Що таке Spring Data JPA і чому це “магія” працює
Spring Data JPA — це надбудова над JPA/Hibernate, яка:
- автоматично створює реалізацію репозиторію “під капотом”;
- генерує SQL запити на основі методів;
- дає стандартний набір CRUD-операцій для кожної сутності.
Ти пишеш інтерфейс, а Spring під час запуску створює клас-реалізацію (через проксі). Тому в нас немає класу UserRepositoryImpl — але все працює.
4) Розбір JpaRepository<User, Long> по частинах
User — сутність, тобто таблиця users.
Це означає: репозиторій буде робити SQL саме для таблиці users.
Long — тип первинного ключа (id).
Має збігатися з типом поля id у сутності User: private Long id; або private long id;
Якщо ти випадково поставиш Integer замість Long — будуть дивні помилки, бо Spring не зможе правильно працювати з id.
5) Які методи ми отримали автоматично (без жодного коду)
Після extends JpaRepository у нас вже є десятки методів. Найважливіші:
- save(entity) — вставка/оновлення (INSERT або UPDATE)
- findAll() — отримати всі записи
- findById(id) — знайти по id (повертає Optional)
- existsById(id) — перевірити, чи існує запис
- deleteById(id) — видалити по id
- count() — кількість записів у таблиці
Ключовий момент: Це не “наші” методи — вони вже реалізовані в Spring Data. Ми просто підключили їх для нашої сутності.
6) Як Spring вирішує: INSERT чи UPDATE у save()?
Spring Data JPA дивиться на поле id:
- якщо id = null (або 0 для примітиву) → це новий об’єкт → робить INSERT;
- якщо id вже є → вважає, що запис існує → робить UPDATE.
Тому правильна генерація id через @GeneratedValue критично важлива.
7) Питання студентів: “А де анотація @Repository?”
У багатьох прикладах ви побачите @Repository, але тут ми її не писали. Чому все одно працює?
- Spring Data JPA автоматично реєструє інтерфейси-репозиторії як Spring Beans;
- тобто він сам “помічає” їх як репозиторії під час сканування.
Висновок: у Spring Data JPA анотація @Repository часто не потрібна явно. Але концептуально репозиторій — це саме Repository-компонент.
8) Як додавати власні методи: “магія назв” (Derived Queries)
Фішка Spring Data: ти можеш написати метод в інтерфейсі, і Spring згенерує SQL за його назвою.
Наприклад, якщо в User є поле email, ми можемо додати:
І Spring сам зробить приблизно такий SQL:
Тобто ми не пишемо запит. Ми описуємо “що хочемо” в назві методу.
Правило: назва методу має відповідати полю сутності. Якщо поле називається email, то метод має містити ByEmail.
9) Repository vs Service: де має бути логіка?
Репозиторій — це “доступ до даних”. Бізнес-логіка має бути в Service.
- Repository: save, find, delete, прості запити.
- Service: перевірки, правила, обробка помилок, транзакції, об’єднання кількох репозиторіїв.
Якщо логіку пхати в Repository — код стає важко підтримувати. У нормальному проєкті репозиторій максимально “тупий”, сервіс — “розумний”.
10) Типові помилки (щоб одразу попередити)
- Забули залежність Spring Data JPA → JpaRepository не працює.
- Не збігається тип ID (User має Long, а в репозиторії Integer) → помилки типів.
- Метод findByEmail написали, а поля email у сутності немає → Spring впаде при старті.
- Repository викликають з Controller напряму → потім важко додати логіку/перевірки.
Підсумок: репозиторій — це “двері” в базу даних. Тепер ми можемо читати і зберігати User без SQL. Наступний крок — створити Service, щоб додати логіку і зробити код правильно структурованим.