11. Как сохранять в базе данных коллекции базовых типов?
UNKNOWNЕсли у нашей сущности есть поле с коллекцией, то мы привыкли ставить над ним аннотации @OneToMany либо @ManyToMany. Но данные аннотации применяются в случае, когда это коллекция других сущностей (entities). Но что, если у нашей сущности коллекция не других сущностей, а базовых или встраиваемых (embeddable) типов, то есть коллекция элементов?
Для этих случаев в JPA имеется специальная аннотация @ElementCollection, которая указывается в классе сущности над полем коллекции базовых или встраиваемых типов.
Все записи коллекции хранятся в отдельной таблице, то есть в итоге получаем две таблицы: одну для сущности, вторую для коллекции элементов.
Конфигурация для таблицы коллекции элементов указывается с помощью аннотации @CollectionTable, которая используется для указания имени таблицы коллекции и JoinColumn, который ссылается на первичную таблицу.

@Entity
public class Customer {
@Id
@GeneratedValue
private int id;
private String name;
@ElementCollection
private List<String> phoneNumbers;
.............
}
Аннотация @ElementCollection похожа на отношение @OneToMany, за исключением того, что целью являются базовые и встраиваемые типы, а не сущности.
Можно использовать аннотации @AttributeOverrides и @AttributeOverride для настройки отображения в таблице полей базовых или встраиваемых типов.
Коллекции могут иметь тип java.util.Map, которые состоят из ключа и значения.
Для этого типа коллекций применяются следующие правила:
- Ключ или значение Map может быть базовым типом языка программирования Java, встраиваемым классом или сущностью.
- Если значение Map является встраиваемым классом или базовым типом, используйте аннотацию @ElementCollection. Пример.
- Если значение Map является сущностью, используйте аннотацию @OneToMany или @ManyToMany. Пример.
- Использовать тип Map только на одной стороне двунаправленной связи.
Аннотация @MapKeyColumn позволяет настроить столбец «ключ» в таблице Map. Аннотация @Column позволяет настроить столбец «значение» в таблице Map.
Пример.
Использование коллекций элементов имеет один большой недостаток: элементы коллекции не имеют идентификатора, и Hibernate не может обращаться индивидуально к каждому элементу коллекции.
Когда мы добавляем новый объект в коллекцию или удаляем из коллекции существующий элемент, Hibernate удаляет все строки из таблицы элементов и вставляет новые строки по одной для каждого элемента в коллекции. То есть при добавлении одного элемента в коллекцио Hibernate не добавит одну строку в таблицу коллекции, а очистит её и заполнит по новой всеми элементами.
Поэтому коллекции элементов следует использовать только для очень маленьких коллекций, чтобы Hibernate не выполнял слишком много операторов SQL. Во всех других случаях рекомендуется использовать коллекции сущностей с @OneToMany.
Предыдущий вопрос: 10. Как мапятся даты (до Java 8 и после)?
Следующий вопрос: 12. Какие существуют виды связей?
Все вопросы по теме: список
Все темы: список
Вопросы/замечания/предложения/нашли ошибку: напишите мне