Embedded Types, Enums and Collections in JPA

Site Admin · 11 Sep 2026 · 9 views

Embedded Types, Enums and Collections in JPA

JPA entities do not have to consist only of simple fields like String and Long. You can embed value objects directly into a table, map enumerated constants, and store collections of basic values. These features let you model complex domain objects while keeping the database schema clean.

Embedding Value Objects

An embedded type is a plain Java class that has no identity of its own. Instead, its fields are stored as columns in the owning entity's table. Common examples are Address, Money, or DateRange. JPA uses the @Embeddable and @Embedded annotations to wire them up:

@Embeddable
public class Address {

    private String street;
    private String city;
    private String state;
    private String zipCode;

    // getters and setters
}

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name = "street", column = @Column(name = "home_street")),
        @AttributeOverride(name = "city", column = @Column(name = "home_city"))
    })
    private Address homeAddress;

    // getters and setters
}

The @Embeddable annotation marks Address as a value type. @Embedded on the User field tells Hibernate to flatten its columns into the users table. @AttributeOverrides lets you rename columns when the same embedded type is used multiple times.

Mapping Enums

Enumerations are a natural fit for fields like status, role, or priority. JPA can persist enums as strings or integers. The string form is more readable in the database; the ordinal form is slightly faster but fragile if enum order changes:

public enum OrderStatus {
    PENDING, PROCESSING, SHIPPED, DELIVERED, CANCELLED
}

@Entity
@Table(name = "orders")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false, length = 20)
    private OrderStatus status;

    // getters and setters
}

@Enumerated(EnumType.STRING) stores the enum name as a VARCHAR. Always prefer STRING over ORDINAL because reordering or inserting enum values changes ordinals and corrupts existing data.

Collections of Basic Types

Sometimes you need a list of simple values tied to a single entity - like a set of tags or a list of phone numbers. JPA supports this with @ElementCollection, which stores the values in a separate table:

@Entity
@Table(name = "products")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @ElementCollection
    @CollectionTable(name = "product_tags", joinColumns = @JoinColumn(name = "product_id"))
    @Column(name = "tag")
    private Set<String> tags = new HashSet<>();

    // getters and setters
}

Hibernate creates a product_tags table with a foreign key back to products and a column for each tag value. This keeps the products table clean while letting you query and filter by tags.

Real-World Scenario

An e-commerce platform uses an embedded Address on Customer for shipping and billing, an enum for OrderStatus on every order, and an element collection of tags on each Product for search filtering. These modeling techniques keep the schema normalized without sacrificing clean domain objects.

Key Points

  • @Embeddable and @Embedded flatten a value object into the owning table's columns.
  • @AttributeOverrides lets you rename columns when embedding the same type multiple times.
  • Use @Enumerated(EnumType.STRING) to persist enums as strings - never use ORDINAL.
  • @ElementCollection stores collections of basic types in a separate table.
  • Embedded types have no identity - they live and die with the owning entity.
Share this post:

Comments (0)

Please login or register to comment.