Hibernate @MapKeyClass for Managing Map in Entity

Paul Ravvich
Hibernate At the Gates of Mastery
3 min readApr 21, 2024

--

Hibernate offers powerful features for managing collections in your database. One such feature is the @MapKeyClass annotation, which allows you to specify the class that will be used as the key in a Map.

@MapKeyClass in Hibernate: Managing Entity Maps

Hi, this is Paul, and welcome to this article, we explore how to use @MapKeyClass annotation for managing Map data structure in Hibernate.

Concept of @MapKeyClass

The @MapKeyClass annotation is used in Hibernate to specify the class of keys when entities are associated using a Map collection. This is particularly useful when the keys of the collection need to be of a type other than standard data types. Using @MapKeyClass allows Hibernate to handle keys correctly, generating accurate SQL queries for data insertion, update, and retrieval operations.

Example Usage

Let’s consider an example where art galleries contain a map of paintings classified by artistic style.

Database Setup

First, let’s create the necessary tables in the database:

CREATE TABLE art_galleries
(
id BIGSERIAL PRIMARY KEY,
name VARCHAR(255)
);

CREATE TABLE paintings
(
id BIGSERIAL PRIMARY KEY,
title VARCHAR(255),
artist VARCHAR(255),
style VARCHAR(255),
gallery_id BIGINT,
FOREIGN KEY (gallery_id) REFERENCES art_galleries(id)
);

Hibernate Entities

Next, define the entities:

import jakarta.persistence.*;
import lombok.*;

import java.util.HashMap;
import java.util.Map;

@Entity
@Getter
@Setter
@Builder
@ToString(exclude = "paintings")
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "art_galleries")
public class ArtGallery {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "name")
private String name;

@OneToMany(mappedBy = "gallery", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@MapKeyClass(ArtStyle.class)
@BatchSize(size = 10) // for prevent N+1 problem
private Map<ArtStyle, Painting> paintings = new HashMap<>();
}
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class ArtStyle {
@Column(name = "style")
private String style;
}
import jakarta.persistence.*;
import lombok.*;

@Entity
@Getter
@Setter
@Builder
@ToString(exclude = "gallery")
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "paintings")
public class Painting {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "title")
private String title;

@Column(name = "artist")
private String artist;

@Embedded
private ArtStyle style;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "gallery_id")
private ArtGallery gallery;
}

Key Points Analysis

The key aspect of this example is the use of @MapKeyClass, which tells Hibernate to use the ArtStyle class as the map key. This allows easy retrieval and management of artworks organized by style at the object level.

Advantages and Limitations

Advantages

  • Type Safety: Using specific classes for keys enhances type safety.
  • Flexibility: Allows the use of complex data structures as keys.
  • Simplified Queries: Simplifies database queries when working with collection relationships.

Limitations

  • Complexity: Requires additional configuration and understanding of relationships in Hibernate.
  • Performance: Using complex keys may affect performance with large data volumes. And potential N+1 problem

Conclusion

@MapKeyClass provides an effective way to manage complex relationships between entities in Hibernate. When used correctly, it can significantly simplify the development of applications that work with complex data models.

Thank you for reading until the end. Before you go:

Paul Ravvich

--

--

Paul Ravvich
Hibernate At the Gates of Mastery

Software Engineer with over 10 years of XP. Join me for tips on Programming, System Design, and productivity in tech! New articles every Tuesday and Thursday!