Repository: доступ до бази без SQL
Репозиторій — це шар між нашим кодом і базою даних. Ми викликаємо методи Java, а Spring Data JPA сам генерує SQL.
Рис. 5 Інтерфейс UserRepository, який наслідує JpaRepository<User, Long>. Це одна стрічка — а можливостей додає дуже багато.

### 1) Що таке репозиторій (Repository) простими словами

Repository — це компонент, який “вміє” працювати з таблицею в базі даних: зберігати, читати, оновлювати і видаляти записи.

Уяви це як “пульт керування таблицею”:

- натиснув save() → запис зберігся в БД
- натиснув findAll() → отримав всі записи
- натиснув findById() → отримав конкретний рядок
- натиснув deleteById() → видалив запис

Головна ідея: у коді ми не пишемо SQL “руками”. Ми працюємо методами Java, а Spring Data JPA перетворює це на SQL.

### 2) Що ми зробили конкретно тут

Ми створили інтерфейс:

public interface UserRepository extends JpaRepository<User, Long> {}

Тобто ми сказали 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, ми можемо додати:

Optional<User> findByEmail(String email);

І Spring сам зробить приблизно такий SQL:

SELECT * FROM users WHERE email = ?;

Тобто ми не пишемо запит. Ми описуємо “що хочемо” в назві методу.

Правило: назва методу має відповідати полю сутності. Якщо поле називається 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, щоб додати логіку і зробити код правильно структурованим.