Сохранение коллекций базовых типов Hibernate

Для коллекции значений, которые не являются сущностями, используется @ElementCollection.

@ElementCollection
@CollectionTable(
    name = "customer_phone",
    joinColumns = @JoinColumn(name = "customer_id")
)
@Column(name = "phone", nullable = false)
private Set<String> phones = new HashSet<>();

Элементы могут быть простыми типами, enum или @Embeddable.

Модель жизни

Коллекция принадлежит сущности:

  • элементы не имеют отдельного @Id;
  • не загружаются через собственный репозиторий;
  • сохраняются и удаляются вместе с владельцем;
  • по стандарту загружаются LAZY.

При изменении списка Hibernate в зависимости от маппинга может удалить и вставить несколько строк вместо точечного update. Большая и часто изменяемая коллекция — кандидат на отдельную entity.

List, Set и Map

  • Set требует корректных equals/hashCode элемента и выражает уникальность в модели, но БД также нуждается в UNIQUE;
  • List без @OrderColumn не хранит стабильную позицию;
  • @OrderColumn добавляет индекс позиции, и вставка в начало может обновить много строк;
  • Map требует маппинга ключа через @MapKey....

Вопросы для повторения

  1. Чем @ElementCollection отличается от @OneToMany? Элемент — value object без собственной идентичности.
  2. Можно ли сослаться на один элемент из другой сущности? Нет как на самостоятельную entity.
  3. Почему большая коллекция значений проблемна? Изменение может породить много delete/insert и раздувать граф владельца.
  4. Гарантирует ли Set уникальность в БД? Нет, нужно ограничение схемы.

Связано: Встраиваемый класс Embeddable, Fetch type Hibernate, Связи таблиц.