Stockage d'une carte <String, String> à l'aide de JPA


103

Je me demande s'il est possible d'utiliser des annotations pour conserver la attributescarte dans la classe suivante en utilisant JPA2

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

Comme nous avons déjà une base de données de production préexistante, les valeurs de attributes pourraient idéalement correspondre à la table existante suivante:

create table example_attributes {
    example_id bigint,
    name varchar(100),
    value varchar(100));

Réponses:


201

JPA 2.0 prend en charge les collections de primitives via l' @ElementCollectionannotation que vous pouvez utiliser conjointement avec la prise en charge des java.util.Mapcollections. Quelque chose comme ça devrait fonctionner:

@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

}

Voir aussi (dans la spécification JPA 2.0)

  • 2.6 - Collections de classes intégrables et de types de base
  • 2.7 Collections de cartes
  • 10.1.11 - Annotation ElementCollection
  • 11.1.29 Annotation MapKeyColumn

1
Existe-t-il une solution de contournement pour faire cela en utilisant JPA 1? Je n'ai trouvé que des exemples avecMap<String, SomeOtherClass>
L. Holanda

3
Cela vaut peut-être la peine de mentionner qu'il example_attributesdevrait avoir une clé composite (example_id, name)- c'est ce que hbm2ddl générera à partir de ce qui précède.
James Bassett

J'ai essayé l'exemple ci-dessus, mais en essayant de persister une entité, j'obtiens une exception: vous devez définir au moins un mappage pour cette table. Requête: InsertObjectQuery (null). Des indices? Je crée une entité vide et définit la carte des propriétés, puis j'essaye de persister.
Kamila le

2
En utilisant MariaDB, je suis tombé sur le Specified key was too long; max key length is 767 bytesfaire. La clé primaire qu'il tente de créer est une combinaison de varchar (255) et de @JoinColumn, qui dépasse la taille de colonne par défaut. Vous devez soit changer votre base de données, soit modifier votre @MapKeyColumn pour fournir une longueur:@MapKeyColumn(name="name", length=100)
Jon

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>();

Ceci est un exemple sur la façon de configurer une carte avec un contrôle sur les noms de colonnes et de tables et la longueur des champs.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.