Mapping a map of simple types in JPA using @ElementCollection

In the previous post I have shown how to easily map a collection (e.g. Set or List) of simple types in JPA. Today I would like to present how we achieve something similar for Java maps like HashMap or TreeMap.

Mapping a map

Assume that there is a requirement to keep a quantity for each item sold in the store. If the item can be uniquely identified by its name only (no additional information about item is needed), it can be defined as a plain Map<String, Integer> with few JPA annotations:

@Entity
public class Store {
  @Id
  protected long id;

  @ElementCollection
  @CollectionTable(name = "item_quantity",
        joinColumns = { @JoinColumn(name = "store_id") })
  @MapKeyColumn(name = "item")
  @Column(name = "quantity")
  protected Map<String, Integer> itemQuantityMap = new HashMap<>();

The first annotation @ElementCollection is required and is needed to inform JPA provider that a map is used. The rest of the annotations are optional and are used to customize the schema.

The @CollectionTable annotation specifies the name of the DB table where the map keys and values are stored. In this case the new table is named item_quantity. This new table refers to the parent entity Store through a foreign key. The definition of the column holding the foreign key is specified in joinColumns parameter.

The @Column annotation defines the properties (e.g. name) of the column in the new table where the values of the Map are stored.

The @MapKeyColumn does something similar to @Column but for the keys of the map. It defines the properties of the column where the keys of the Map are stored.

Enumerated types in key

The key of the map can be of enumerated type. In this case JPA provider stores the ordinal of the enum in the database table by default. If the name of the enum should be used instead, it can be changed using @MapKeyEnumerated annotation like this:

   ...
   @MapKeyEnumerated(STRING)
   protected Map<TypeEnum, Integer> map;

In practice, @MapKeyEnumerated can be treated as an equivalent of @Enumerated in case of map keys.

Date types in key

If the key of the map represents date or time (e.g. java.util.Date), the annotation @MapKeyTemporal is required. This annotation is an equivalent of @Temporal in case of map keys.

About Robert Piasecki

Husband and father, Java software developer, Linux and open-source fan.
This entry was posted in Hibernate, JPA and tagged , . Bookmark the permalink.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.