Сьогодні наше завдання — виконати другий проєкт на тему Hibernate. Його суть — розібратися в структурі БД, зробити мапінг ентіті на існуючі таблиці та додати мінімальний функціонал для перевірки того, чи мапінг виконаний правильно.

Тепер докладніше:

  1. Завантаж дамп-файл та розгорни його у себе на локальній машині. За БД ми будемо використовувати тестову БД, яка поширюється як приклад разом із інсталяційним пакетом MySQL. Дамп необхідний для того, щоб зафіксувати стан БД, оскільки ми не можемо гарантувати, що вона не зміниться через день-місяць-рік.
  2. Темпліту проєкту ми не матимемо, тому проєкт створи самостійно. Це повинен бути maven проєкт з усіма необхідними залежностями (hibernate-core-jakarta, mysql-connector-java, p6spy).
  3. Підключи в IDEA нашу локальну розгорнуту БД як datasource. Після цього у вкладці Database постав курсор на схему movie і натисни комбінацію клавіш Alt+Ctrl+Shift+U (працює лише в Ultimate версії). Це покаже структуру всієї схеми movie (з назвою колонок, ключами тощо). Виглядає це приблизно так:

    Згоден, дивитися не дуже зручно. Вимкни показ назви всіх колонок та коментарів:

    У результаті отримаєш схему БД, яку вже можна аналізувати:

  4. Схема виглядає складно, але не так погано. Для аналізу структури БД необхідно визначити з чого почати. Одної правильної відповіді немає, але рекомендуємо почати з таблиці film. Давай розглянемо кілька взаємозв'язків як приклад:
    • Зв'язок між таблицями film та film_text — це явний зв'язок OneToOne, тому що в таблиці film_text є поле film_id, яке НЕ посилається на ID з таблиці film (немає foreign key). Але з огляду на назву та логіку, цей зв'язок має бути. До того ж, у таблиці film_text поле film_id виступає первинним ключем, що гарантує, що одному «фільму» відповідає лише один «текст фільму».
    • Тепер давай подивимося на таблиці film та category. З погляду логіки, фільм може мати кілька категорій. І одна категорія може бути в різних фільмів. Крім цього, між двома таблицями є проміжна таблиця зв'язку film_category. Виходячи з усього, що перераховано вище, це явний зв'язок ManyToMany.
    • Дивимося на таблиці film та language. З точки зору логіки, у фільму може бути переклад різними мовами і різні фільми можуть бути однією мовою. Тобто напрошується ManyToMany. Але якщо подивитися на вміст film, ми можемо помітити, що кожен рядок таблиці — це унікальний фільм. І в рядку є тільки одне поле language_id (є ще original_language_id, але у всіх записах воно null, тому можемо не звертати на нього увагу). Тобто в одного фільму може бути лише одна мова. І одна мова може бути в різних фільмів. Зв'язок — ManyToOne (зв'язок, спрямований від film до language).
  5. Тепер основне завдання — створити всі необхідні ентіті класи та замапити їх на таблиці схеми movie.
  6. Додати метод, який вміє створювати нового покупця (таблиця customer) з усіма залежними полями. Не забудь зробити так, щоб спосіб був транзакційним (щоб не потрапити в ситуацію, що адресу покупця записали до БД, а самого покупця — ні).
  7. Додати транзакційний метод, який описує подію «покупець пішов і повернув раніше орендований фільм». Покупця та подію оренди обери будь-які на власний розсуд. Рейтинг фільму не треба перераховувати.
  8. Додати транзакційний метод, який описує подію «покупець сходив до магазину (store) та орендував (rental) там інвентар (inventory). При цьому він здійснив оплату (payment) у продавця (staff)». Фільм (через інвентар) обери на власний розсуд. Єдине обмеження — фільм має бути доступним для оренди. Тобто або у rental не повинно бути взагалі записів про інвентар, або має бути заповнена колонка return_date таблиці rental для останньої оренди цього інвентарю.
  9. Додати транзакційний метод, який описує подію «зняли новий фільм, і він став доступним для оренди». Фільм, мову, акторів, категорії тощо обери на власний розсуд.
  10. Структуру таблиць міняти не можна. Але внести свої пропозиції щодо покращення — потрібно. Одне проблемне місце ми виявили в п.4 (відсутність foreign key у таблиці film_text на полі film_id таблиці film). Подивися, чи є ще у структурі БД такі «ляпи». Якщо так — додай readme файл у корінь проекту та опиши ці ляпи.

Розбір проєкту: