Ми вже знаємо, що 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 з налаштуванням таблиці і колонок.
- Створи сутність
Productз полями:id— первинний ключ, автоінкремент.name— рядок, не може бути порожнім.price— число, має бути більше нуля.description— текст, допускаєтьсяNULL.
- Налаштуй таблицю з ім'ям
products. - Налаштуй колонку
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 завжди видасть зрозумілу помилку. Головне — не панікувати. 😄
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ