Foundation · Build

Composite Keys & Embeddables

Some rows are identified by two columns together—model that identity with @EmbeddedId and reusable @Embeddable value objects.

Primary source: Jakarta Persistence: Embeddable Classes and Composite Keys

20 min

Lesson 10 of 17

1d streak

The Architectural Question

Forcing every table into a single auto-generated id hides real-world identity: inventory is per warehouse per SKU, and duplicates become possible the moment you relax that key.

What this guide proves

  • Define identity with an @Embeddable id record
  • Query composite keys through derived id-part methods
  • Recognize when a surrogate key serves better than a composite one

Domain Value Objects with @Embeddable

Not every table column needs to be a primitive String or Long on the entity. Value objects (like Money, Address, or TaxDetails) can be grouped into @Embeddable classes that map cleanly into the host entity’s table columns without extra joins.

Money.java
@Embeddable
public record Money(
    @Column(name = "amount", nullable = false) BigDecimal amount,
    @Column(name = "currency", nullable = false, length = 3) String currency
) {}

Composite primary keys with @EmbeddedId

For join tables with payload attributes (e.g. OrderItemId containing orderId and productId), create an @Embeddable class implementing Serializable with proper equals() and hashCode().

Active Recall Checkpoint

What interface must an @Embeddable composite primary key implement?

Hint: JPA requires entity identifiers to be serializable.

Show answer & explanation

java.io.Serializable. Composite keys must also implement stable equals() and hashCode() based on all constituent key properties.

When to use composite keys

Use it when

Use @Embeddable to create rich, type-safe Domain-Driven Design value objects that share the entity table.

Reconsider when

Prefer synthetic surrogate keys (UUIDs) over complex composite keys when the table is referenced as a foreign key by multiple downstream tables.

Runtime Architecture & Flow

Structure under inspection

Composite Keys & Embeddables

Part 1

Define identity with an @Embeddable id record

Part 2

Query composite keys through derived id-part methods

Part 3

Recognize when a surrogate key serves better than a composite one

The connectors show containment and responsibility—not time or call order.

Synthesis & Production Verification

Deliberate Failure Condition

  1. Break: Implement equals and hashCode inconsistently on a composite id class
  2. Observe: Entities duplicate inside persistence contexts and Set membership behaves unpredictably
  3. Repair: Composite ids live in maps and contexts by value equality; a record or disciplined equals/hashCode is mandatory, not optional.

Production Acceptance Criteria

  • Persist and find entities by an @EmbeddedId record
  • Write a derived query navigating id parts
  • Argue surrogate vs composite choice for one real table

Architectural & Technical Review

Core Interview Questions

Q01When should you model domain attributes with @Embeddable?Show answer

When grouping related value object fields (like Money or Address) that share the same database table with the entity.

Q02What requirements must an @EmbeddedId class fulfill?Show answer

It must implement Serializable and provide stable equals() and hashCode() based on all composite key fields.

Q03How do value objects improve domain models in Spring Boot?Show answer

They enforce domain validation at construction time and prevent primitive obsession across service boundaries.

Production Pitfalls

Critical Anti-Patterns

  • Pitfall: Using mutable setters on @Embeddable value objects — Value objects should represent immutable snapshots; mutability creates aliasing bugs across entity graphs.
  • Pitfall: Creating deep foreign keys targeting composite primary keys — Composite keys propagate multiple columns to every child table, complicating queries and foreign key indexes.

Primary Documentation & Specifications