«1. Обзор

В этом руководстве мы увидим, как можно сопоставить одну сущность, содержащую встроенные свойства, с одной таблицей базы данных.

Итак, для этой цели мы будем использовать аннотации @Embeddable и @Embedded, предоставляемые Java Persistence API (JPA).

2. Контекст модели данных

Прежде всего, давайте определим таблицу с именем company.

В таблице company будет храниться основная информация, такая как название компании, адрес и телефон, а также информация о контактном лице:

public class Company {

    private Integer id;

    private String name;

    private String address;

    private String phone;

    private String contactFirstName;

    private String contactLastName;

    private String contactPhone;

    // standard getters, setters
}

Контактное лицо, похоже, должно быть абстрагировано отдельный класс. Проблема в том, что мы не хотим создавать отдельную таблицу для этих деталей. Итак, давайте посмотрим, что мы можем сделать.

3. @Embeddable

JPA предоставляет аннотацию @Embeddable для объявления того, что класс будет внедрен другими объектами.

Давайте определим класс для абстрагирования сведений о контактном лице:

@Embeddable
public class ContactPerson {

    private String firstName;

    private String lastName;

    private String phone;

    // standard getters, setters
}

4. @Embedded

Аннотация JPA @Embedded используется для встраивания типа в другой объект.

Давайте теперь изменим наш класс Company. Мы добавим аннотации JPA, а также изменим использование ContactPerson вместо отдельных полей:

@Entity
public class Company {

    @Id
    @GeneratedValue
    private Integer id;

    private String name;

    private String address;

    private String phone;

    @Embedded
    private ContactPerson contactPerson;

    // standard getters, setters
}

В результате у нас есть сущность Company, включающая данные контактного лица и сопоставление с одной таблицей базы данных.

У нас все еще есть еще одна проблема, и это то, как JPA будет отображать эти поля в столбцы базы данных.

5. Переопределение атрибутов

Дело в том, что наши поля назывались такими вещами, как contactFirstName в нашем исходном классе Company, а теперь firstName в нашем классе ContactPerson. Таким образом, JPA захочет сопоставить их с contact_first_name и first_name соответственно.

Помимо того, что это далеко не идеально, это на самом деле сломает нас с нашей теперь дублированной телефонной колонкой.

Итак, мы можем использовать @AttributeOverrides и @AttributeOverride для переопределения свойств столбца нашего встроенного типа.

Давайте добавим это в поле ContactPerson в нашей сущности Company:

@Embedded
@AttributeOverrides({
  @AttributeOverride( name = "firstName", column = @Column(name = "contact_first_name")),
  @AttributeOverride( name = "lastName", column = @Column(name = "contact_last_name")),
  @AttributeOverride( name = "phone", column = @Column(name = "contact_phone"))
})
private ContactPerson contactPerson;

Обратите внимание, что, поскольку эти аннотации помещаются в поле, у нас могут быть разные переопределения для каждой включающей сущности.

6. Заключение

В этом руководстве мы настроили объект с некоторыми встроенными атрибутами и сопоставили их с той же таблицей базы данных, что и объемлющий объект. Для этого мы использовали аннотации @Embedded, @Embeddable, @AttributeOverrides и @AttributeOverride, предоставляемые Java Persistence API.

Как всегда, исходный код примера доступен на GitHub.