A Java Map associates each key with at most one value. In a persistent domain model, that makes it useful when an entity’s collection is naturally addressed by a name or another unique key. Declare the property with the Map interface, give it generic key and value types, and initialize it immediately with an implementation such as HashMap. Hibernate may wrap or replace that collection to support lazy loading and dirty checking. section 8.1.3 section 8.1.7
Listing 8.6 Persistent map storing its key and value pairs
Path: Ch08/mapping-collections/src/main/java/com/manning/javapersistence /ch08/mapofstrings/Item.java @Entity public class Item { // . . . @ElementCollection @CollectionTable(name = "IMAGE") @MapKeyColumn(name = "FILENAME") #1 @Column(name = "IMAGENAME") #2 private Map<String, String> images = new HashMap<>(); #1 Each map entry is a key/value pair. Here the key is mapped with <kbd>@MapKeyColumn</kbd> to <kbd>FILENAME</kbd>. #2 The value is the <kbd>IMAGENAME</kbd> column. This means the user can only use a file once because a <kbd>Map</kbd> doesn’t allow duplicate keys.
A map of strings stores each image’s filename as the key and its user-supplied name as the value. @ElementCollection and @CollectionTable select the collection table; @MapKeyColumn and @Column identify its key and value columns. The table’s primary key combines the owning item’s ID with the filename, so a filename cannot be used twice for that item. section 8.1.7
Choose key and value mappings according to what the application needs to identify:
- For a basic key, @MapKeyColumn names its column. Basic keys can be types other than String; enum keys use @MapKeyEnumerated, and temporal keys use @MapKeyTemporal. section 8.1.7
- For an embeddable value, keep the key column separate from the value’s mapped fields. A Map<String, Image> can use a title as its key while Image holds the filename and dimensions; the filename can then be nullable because it is not part of the primary key. section 8.2.4
- For an embeddable key, its mapped columns become part of the collection table’s composite primary key and cannot be nullable. Implement equals() and hashCode() so keys are unique within the map. @MapKeyColumn does not configure an embeddable key. section 8.2.5
Path: maps-ternary/src/main/java/com/manning/javapersistence /ch09/maps/ternary/Category.java @Entity public class Category { // . . . @ManyToMany(cascade = CascadeType.PERSIST) @MapKeyJoinColumn(name = "ITEM_ID") #1 @JoinTable( name = "CATEGORY_ITEM", joinColumns = @JoinColumn(name = "CATEGORY_ID"), inverseJoinColumns = @JoinColumn(name = "USER_ID") ) private Map<Item, User> itemAddedBy = new HashMap<>(); // . . . } #1 The <kbd>@MapKeyJoinColumn</kbd> is optional; Hibernate or Spring Data JPA using Hibernate will default to the column name <kbd>ITEMADDEDBY_KEY</kbd> for the join/foreign key column referencing the <kbd>ITEM</kbd> table.
Maps can also hold entity references. Here an owning category maps each item key to the user who added it. @MapKeyJoinColumn identifies the item foreign key, while @JoinTable maps the three-column link table. The relationship has a compact Map API, but a link that later needs extra data may require a different model and application-code changes. section 9.4.2
Use a Map when lookup by a unique key expresses the relationship itself—not merely to avoid a separate link class. Unlike a List, it does not preserve positions through an index column. Decide whether the key is a basic value, an embeddable value, or an entity reference before choosing its mapping annotations and table key. section 8.1.6 section 9.4.2









































