Встраиваемые объекты
В приводившемся ранее в этой главе подразделе «Составные первичные ключи» вы видели, как класс может быть встроен и использован в качестве первичного ключа с применением аннотации @EmbeddedId. Встраиваемые объекты — это объекты, которые сами по себе не имеют постоянного идентификатора; они могут быть только встроены во владеющие сущности. Владеющая сущность может располагать коллекциями встраиваемых объектов, а также одним встраиваемым атрибутом. Они сохраняются как внутренняя часть владеющей сущности и совместно используют идентификатор этой сущности. Это означает, что каждый атрибут встроенного объекта будет отображаться в таблицу сущности. Это связь строгого владения (также называемая композицией), поэтому если удалить сущность, то встроенные объекты тоже окажутся удалены.
Эта композиция между двумя классами задействует аннотации. Для включенного класса используется аннотация @Embeddable, в то время как в отношении сущности, которая включает этот класс, используется @Embedded. Обратимся к примеру клиента, у которого имеется идентификатор, имя, адрес электронной почты, а также домашний адрес. Все соответствующие атрибуты могли бы располагаться в одной сущности Customer (листинг 5.31), однако по причинам объектного моделирования они разделены на два класса: Customer и Address. Поскольку у Address нет собственного идентификатора, и при этом он всего лишь часть состояния Customer, этот класс является хорошим кандидатом на то, чтобы стать встраиваемым объектом вместо сущности (листинг 5.30).
@Embeddable
public class Address {
··private String street1;
··private String street2;
··private String city;
··private String state;
··private String zipcode;
··private String country;
··// Конструкторы, геттеры, сеттеры
}
Как вы можете видеть в листинге 5.30, класс Address аннотирован не как сущность, а как встраиваемый объект. Аннотация @Embeddable определяет, что Address может быть встроен в иной класс-сущность (или иной встраиваемый объект). С другой стороны, для сущности Customer приходится использовать аннотацию @Embedded, чтобы определить, что Address является постоянным атрибутом, который будет сохранен как внутренняя часть и станет совместно использовать его идентификатор (см. листинг 5.31).
@Entity
public class Customer {
··@Id @GeneratedValue
··private Long id;
··private String firstName;
··private String lastName;
··private String email;
··private String phoneNumber;
··@Embedded
··private Address address;
··// Конструкторы, геттеры, сеттеры
}
Каждый атрибут Address будет отображаться в таблицу владеющей сущности Customer. Будет только одна таблица со структурой, определенной в листинге 5.32. Как вы увидите позднее в подразделе «Переопределение атрибутов» раздела «Отображение наследования» данной главы, сущности могут переопределять атрибуты встраиваемых объектов (с использованием аннотации @AttributeOverrides).
create table CUSTOMER (
··ID BIGINT not null,
··LASTNAME VARCHAR(255),
··PHONENUMBER VARCHAR(255),
··EMAIL VARCHAR(255),
··FIRSTNAME VARCHAR(255),
··STREET2 VARCHAR(255),
··STREET1 VARCHAR(255),
··ZIPCODE VARCHAR(255),
··STATE VARCHAR(255),
··COUNTRY VARCHAR(255),
··CITY VARCHAR(255),
··primary key (ID)
);
В предшествующих разделах я показывал вам, как отображать коллекции и отображения базовых типов данных. В JPA 2.1 то же самое возможно с помощью встраиваемых объектов. Вы можете отображать коллекции встраиваемых объектов, а также отображения таких объектов (встраиваемый объект может быть либо ключом, либо значением отображения).