Что означает аннотация @Embeddable в JPA/Hibernate?

«Что означает аннотация @Embeddable в JPA/Hibernate?» — вопрос из категории Hibernate, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

@Embeddable — это аннотация JPA (Java Persistence API), которая помечает класс как встраиваемый (embeddable). Такой класс не является самостоятельной сущностью (@Entity), но его состояние (поля) может быть сохранено как часть одной или нескольких сущностей.

Ключевая концепция: Композиция объектов в одной таблице базы данных.

Пример использования:

// 1. Определяем встраиваемый класс
@Embeddable
public class Address {
    private String street;
    private String city;
    private String postalCode;
    private String country;

    // Конструкторы, геттеры, сеттеры...
}

// 2. Встраиваем его в сущность
@Entity
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @Embedded // Указывает, что здесь используется встраиваемый объект
    private Address homeAddress;

    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name = "street", column = @Column(name = "work_street")),
        @AttributeOverride(name = "city", column = @Column(name = "work_city"))
    })
    private Address workAddress; // Повторное использование с переопределением имён столбцов
}

Что произойдёт в БД? Будет создана одна таблица customer со столбцами: id, name, street, city, postal_code, country, work_street, work_city. Поля класса Address «разворачиваются» в таблице сущности-владельца.

Основные характеристики и правила:

  • Нет собственного идентификатора: Класс @Embeddable не имеет аннотации @Id и не управляется своим жизненным циклом. Его жизненный цикл полностью зависит от сущности-владельца.
  • Может содержать базовые типы и другие @Embeddable: Встраиваемый класс может включать поля базовых типов, @Enumerated, @Temporal, а также другие классы, помеченные @Embeddable.
  • Может использоваться в @ElementCollection: Для хранения коллекций встраиваемых объектов (например, List<Address>).
  • Повторное использование: Один и тот же @Embeddable класс можно встроить в несколько сущностей.
  • Переопределение столбцов: Аннотации @AttributeOverride и @AttributeOverrides позволяют задавать имена столбцов в БД для каждого конкретного случая встраивания.

Когда использовать? Для моделирования концепций, которые:

  1. Не имеют самостоятельного смысла вне контекста владеющей сущности (например, Адрес, Денежная сумма с валютой, Координаты).
  2. Логически группируют несколько полей, улучшая читаемость объектной модели.
  3. Должны храниться в той же таблице БД, что и владелец (оптимизация запросов, отсутствие JOIN).