··private String description;

··private String isbn;

··private Integer nbOfPage;

··private Boolean illustrations;

··@ElementCollection(fetch = FetchType.LAZY)

··@CollectionTable(name = "Tag")

··@Column(name = "Value")

··private List tags = new ArrayList<>();

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

}

Аннотация @ElementCollection, показанная в листинге 5.24, используется для информирования поставщика постоянства о том, что атрибут tags представляет собой список строк, а его выборка должна быть отложенной. При отсутствии @CollectionTable имя таблицы по умолчанию было бы BOOK_TAGS (конкатенация имени содержащей сущности и имени атрибута коллекции, разделенных знаком подчеркивания), а не TAG, как указано в элементе name (name = "Tag"). Обратите внимание, что я добавил дополнительную аннотацию @Column, чтобы переименовать столбец в VALUE (в противном случае этот столбец получил бы имя, как у атрибута, TAGS). Результат можно увидеть на рис. 5.2.

Рис. 5.2. Связь между таблицами BOOK и TAG

Примечание

В JPA 1.0 этих аннотаций не было. Однако все равно можно было сохранить список примитивных типов, например BLOB, в базе данных. Почему? А потому, что java.util.ArrayList реализует Serializable, а JPA может автоматически отображать сериализуемые объекты в BLOB-объекты. Вместе с тем, если вы взамен используете тип java.util.List, то получите исключение, так как он не расширяет Serializable. Применение @ElementCollection — более элегантный и целесообразный способ сохранения списков базовых типов. Сохранение списков в недоступном двоичном формате не позволит совершать к ним запросы и сделает их непереносимыми в код на других языках (поскольку основной сериализованный объект может быть использован во время выполнения кода, написанного только на Java — не на Ruby, PHP…).

<p>Отображение базовых типов</p>

Как и коллекции, отображения очень полезны при сохранении данных. В JPA 1.0 ключи могли относиться только к базовому типу данных, а значения могли быть только сущностями. Сейчас отображения могут содержать любую комбинацию базовых типов, встраиваемых объектов и сущностей как ключей или значений, что привносит большую гибкость в процесс отображения. Сосредоточимся на отображениях базовых типов.

Когда отображение задействует базовые типы, аннотации @ElementCollection и @CollectionTable могут быть использованы тем же путем, который вы видели ранее в случае с коллекциями. Таблица коллекции тогда будет использоваться для хранения данных отображения.

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

Листинг 5.25. CD-альбом с отображением треков

@Entity

public class CD {

··@Id @GeneratedValue

··private Long id;

··private String title;

··private Float price;

··private String description;

··@Lob

··private byte[] cover;

··@ElementCollection

··@CollectionTable(name="track")

··@MapKeyColumn (name = "position")

··@Column(name = "title")

··private Map tracks = new HashMap<>();

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

}

Я уже говорил, что аннотация @ElementCollection используется как индикатор объектов в отображении, хранящихся в таблице коллекции. Аннотация @CollectionTable изменяет имя по умолчанию таблицы коллекции на TRACK.

Перейти на страницу:

Похожие книги