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-секвенс (особенно полезно в 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 всегда выдаст внятную ошибку. Главное — не паниковать. 😄

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ