How to map a composite key with JPA and Hibernate?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Composite keys are appropriate when row identity is naturally defined by more than one column, such as student_id plus course_id or tenant_id plus external_id. JPA and Hibernate support this well, but the mapping only stays reliable if the key class is stable, serializable, and aligned with the database schema.
Choose Between @EmbeddedId and @IdClass
JPA gives you two main patterns:
- '
@EmbeddedIdkeeps the key in one embeddable value object' - '
@IdClasskeeps key fields directly on the entity with a companion key class'
Both work. In practice, @EmbeddedId is usually easier to reason about because the identity is grouped in one place and can be passed around as a value object.
Recommended Pattern: @EmbeddedId
Start with an embeddable key that implements Serializable and defines stable equality.
Then embed it in the entity.
This is the cleanest baseline mapping.
Use @MapsId for Relationships
If the composite key includes foreign-key columns, map the relationships explicitly with @MapsId instead of duplicating identifier state in several places.
This tells JPA that the relationship columns are also part of the embedded primary key. It keeps the entity mapping aligned with the database design.
@IdClass Is Still Valid
If you prefer direct access to id fields on the entity, @IdClass may fit better.
This style can feel simpler in some queries, but it spreads identity fields across the entity instead of keeping them in one object.
Equality and Mutability Rules Matter
A composite key should behave like a value object. That means:
- fields should represent immutable identity once persisted
- '
equalsandhashCodeshould depend only on key fields' - the key class should not include mutable business data
If key values can change casually after persistence, entity identity becomes difficult for JPA to manage correctly.
Common Pitfalls
The most common mistake is forgetting equals and hashCode on the key class. Without stable equality, collections, caches, and entity identity behavior become unreliable.
Another issue is duplicating key columns both inside the embedded id and again as separate unmanaged fields. That creates synchronization bugs and confusion about which field is authoritative.
Developers also choose composite keys for convenience when a surrogate key plus a unique constraint would be simpler. A composite key is justified when it represents real domain identity, not just because two columns happen to be unique together today.
Finally, be careful with generated values. Composite primary keys usually do not fit naturally with automatic id generation strategies in the same way single-column surrogate keys do.
Summary
- JPA supports composite keys with
@EmbeddedIdand@IdClass. - '
@EmbeddedIdis usually the clearest and most maintainable option.' - Use
@MapsIdwhen foreign-key relationships are part of the composite key. - Keep key classes serializable, stable, and based only on identity fields.
- Choose a composite key only when the domain identity truly depends on multiple columns.

