JavaRush /Курси /Модуль 5. Spring /Анотації JPA: магія @Entity, @Id і @Column

Анотації JPA: магія @Entity, @Id і @Column

Модуль 5. Spring
Рівень 5 , Лекція 2
Відкрита

Ми вже знаємо, що Hibernate і Spring Data JPA — справжні помічники при роботі з базами даних. Вони беруть на себе всю рутину, але як їм це вдається? Зараз розберемося з анотаціями, які перетворюють звичайні Java-класи на повноцінні сутності бази даних.


Вступ в анотації JPA

Забудь про ручне написання SQL-запитів! З анотаціями JPA ти просто кажеш базі даних: "Глянь, цей Java-клас — це таблиця, а його поля — колонки". Зручно, правда?

Анотації JPA працюють як розумні перекладачі. Вони беруть твої об'єкти і пояснюють базі даних, як перетворити їх на зрозумілі таблиці та стовпці.

Вивчати анотації JPA — те саме, що вчити нову мову, тільки набагато простіше. Замість того щоб писати складні SQL-запити, ти працюєш з звичайними Java-об'єктами, а JPA бере на себе всю роботу з перекладу на мову бази даних. Давай розберемо це детальніше.


@Entity — створення "таблиці" з класу

Анотація @Entity — це стартова точка. Вона каже ORM-інструменту (наприклад, Hibernate), що цей клас представляє собою таблицю в базі даних. Наприклад:


import jakarta.persistence.Entity;

@Entity
public class User {
    private Long id;
    private String name;
    private String email;
}

З анотацією @Entity Hibernate розуміє, що клас User відповідає таблиці в базі даних. Це як сказати: "Слухай, Hibernate, тримай, ось моя таблиця, працюй з нею".

Ключові моменти:

  • Якщо ти не помітиш клас як @Entity, Hibernate не включить його в процес ORM. Тобто база даних навіть не дізнається про існування цієї "таблиці".
  • За замовчуванням ім'я таблиці співпадає з ім'ям класу. Однак його можна змінити, як ми розглянемо далі.

Поширена помилка: якщо забути додати @Entity, Hibernate просто проігнорує твій клас, і ти довго будеш ламати голову, чому таблиця не створюється.


@Table — налаштування імені таблиці

Хоча за замовчуванням ім'я таблиці збігається з ім'ям класу, іноді це незручно. Наприклад, в базі даних вже є таблиця з іншим ім'ям. Анотація @Table допомагає настроїти ім'я таблиці.


import jakarta.persistence.Entity;
import jakarta.persistence.Table;

@Entity
@Table(name = "users")
public class User {
    private Long id;
    private String name;
    private String email;
}

Тепер Hibernate створить або зв'яже сутність з таблицею users, а не User.

Додаткові налаштування @Table:

  • schema: вказує схему бази даних.
  • catalog: вказує каталог бази даних.
  • uniqueConstraints: дозволяє задати унікальні обмеження на рівні таблиці.

Цю анотацію ми будемо використовувати рідше, але вміти її налаштовувати корисно.


@Id — ідентифікатор таблиці

Кожна таблиця потребує первинного ключа (primary key), щоб розрізняти рядки. В JPA для цього використовується анотація @Id. Вона позначає поле як ідентифікатор сутності.


import jakarta.persistence.Entity;
import jakarta.persistence.Id;

@Entity
public class User {

    @Id
    private Long id;

    private String name;
    private String email;
}

Тепер Hibernate знає, що поле id в нашому класі — це поле первинного ключа.

Поширена помилка: Якщо ти забудеш додати @Id, Hibernate видасть виключення під час виконання, бо не зможе згенерувати SQL-команди для роботи з таблицею.


@GeneratedValue — генерація ідентифікаторів

Часто значення первинних ключів генеруються автоматично (наприклад, автоінкремент в MySQL). В JPA це можна налаштувати за допомогою @GeneratedValue.


import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String email;
}

Способи генерації:

  • GenerationType.IDENTITY: використовується автоінкремент.
  • GenerationType.SEQUENCE: використовується SQL-sequence (особливо корисно в PostgreSQL).
  • GenerationType.TABLE: генерація ключів через спеціальну таблицю.
  • GenerationType.AUTO: Hibernate вирішить за тебе (частіше використовує SEQUENCE або IDENTITY).

Типова помилка: Якщо ти обираєш GenerationType.IDENTITY для бази даних без автоінкременту, отримаєш помилку під час виконання. Переконайся, що твоя база підтримує обраний спосіб.


@Column — налаштування колонок

Щоб зв'язати поле класу з колонкою таблиці, використовується @Column. За замовчуванням ім'я колонки збігається з ім'ям поля, але @Column дозволяє це змінити.


import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Column;

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "full_name", nullable = false, length = 50)
    private String name;

    @Column(unique = true)
    private String email;
}

Параметри @Column:

  • name: ім'я колонки в таблиці.
  • nullable: визначає, чи може колонка містити NULL.
  • unique: задає унікальне обмеження.
  • length: максимальна довжина рядка.

Тепер колонка name в таблиці буде називатися full_name, не зможе бути пустою і матиме довжину не більше 50 символів.

Типова помилка: якщо довжина рядка перевищує вказане значення в length, ти отримаєш виключення. Крім того, зміна параметрів анотації не завжди автоматично оновлює схему таблиці. Не забувай синхронізувати зміни!


@Transient — виключення поля з мапінгу

Коли твоє поле не повинно зберігатись в базі даних, його можна позначити як @Transient. Це корисно для обчислюваних або тимчасових даних.


import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Transient;

@Entity
public class User {

    @Id
    private Long id;

    private String name;

    @Transient
    private String temporaryToken; // Не зберігається в базі
}

Поле temporaryToken буде існувати тільки в об'єкті User в Java. В таблиці бази даних йому не відповідає жодна колонка.


Практичне завдання

Завдання: створити сутність Product з налаштуванням таблиці і колонок.

  1. Створи сутність Product з полями:
    • id — первинний ключ, автоінкремент.
    • name — рядок, не може бути порожнім.
    • price — число, має бути більше нуля.
    • description — текст, допускається NULL.
  2. Налаштуй таблицю з ім'ям products.
  3. Налаштуй колонку name з максимальною довжиною 100 символів.

Приклад рішення:


import jakarta.persistence.*;

@Entity
@Table(name = "products")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, length = 100)
    private String name;

    @Column(nullable = false)
    private Double price;

    @Column
    private String description;

    // Гетери та сетери
}

Підсумок

Сьогодні ти дізнався, як JPA-анотації перетворюють твої Java-класи на таблиці бази даних. Ти налаштував ідентифікатори через @Id і @GeneratedValue, керував колонками за допомогою @Column, навчився виключати поля з мапінгу за допомогою @Transient, і навіть налаштував ім'я таблиці з використанням @Table.

Пам'ятай: помилитися з анотацією простіше, ніж здається, але Hibernate завжди видасть зрозумілу помилку. Головне — не панікувати. 😄

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ