Сохранение карты <String, String> с использованием JPA

103

Мне интересно, можно ли использовать аннотации для сохранения attributesкарты в следующем классе с использованием JPA2

public class Example {
    long id;
    // ....
    Map<String, String> attributes = new HashMap<String, String>();
    // ....
}

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

create table example_attributes {
    example_id bigint,
    name varchar(100),
    value varchar(100));
коридорас
источник

Ответы:

201

JPA 2.0 поддерживает коллекции примитивов через @ElementCollectionаннотации, которые вы можете использовать вместе с поддержкой java.util.Mapколлекций. Примерно так должно работать:

@Entity
public class Example {
    @Id long id;
    // ....
    @ElementCollection
    @MapKeyColumn(name="name")
    @Column(name="value")
    @CollectionTable(name="example_attributes", joinColumns=@JoinColumn(name="example_id"))
    Map<String, String> attributes = new HashMap<String, String>(); // maps from attribute name to value

}

См. Также (в спецификации JPA 2.0)

  • 2.6 - Коллекции встраиваемых классов и базовых типов
  • 2.7 Коллекции карт
  • 10.1.11 - Аннотация ElementCollection
  • 11.1.29 Аннотация MapKeyColumn
Паскаль Тивент
источник
1
Есть ли способ сделать это с помощью JPA 1? Я нашел только примеры сMap<String, SomeOtherClass>
L. Holanda
3
Возможно, стоит упомянуть, что у него example_attributesдолжен быть составной ключ (example_id, name)- который hbm2ddl сгенерирует из приведенного выше.
Джеймс Бассетт
Я пробовал приведенный выше пример, но при попытке сохранить объект я получаю исключение: вы должны определить хотя бы одно сопоставление для этой таблицы. Запрос: InsertObjectQuery (null). Есть подсказки? Я создаю пустую сущность и устанавливаю карту свойств, а затем пытаюсь продолжить.
Камила
2
Используя MariaDB, я столкнулся с Specified key was too long; max key length is 767 bytesэтим. Первичный ключ, который он пытается создать, представляет собой комбинацию varchar (255) и @JoinColumn, что превышает размер столбца по умолчанию. Вам нужно либо изменить свою базу данных, либо изменить свой @MapKeyColumn, чтобы указать длину:@MapKeyColumn(name="name", length=100)
Джон,
18
  @ElementCollection(fetch = FetchType.LAZY)
  @CollectionTable(name = "raw_events_custom", joinColumns = @JoinColumn(name =     "raw_event_id"))
  @MapKeyColumn(name = "field_key", length = 50)
  @Column(name = "field_val", length = 100)
  @BatchSize(size = 20)
  private Map<String, String> customValues = new HashMap<String, String>();

Это пример того, как настроить карту с контролем над именами столбцов и таблиц, а также длиной поля.

Wciesiel
источник