@Embeddable & @Embedded
Intermediate@Embeddable defines a reusable value-type POJO; @Embedded includes its columns in the owning entity table. Use for Address, Money, or other value objects with no identity.
Overview
@Embeddable marks a class as a value type — it has no identity of its own and its columns are physically stored in the owning entity's table. @Embedded on a field includes those columns inline. This enables rich domain models (DDD value objects like Address, Money, DateRange) without extra join tables. Multiple embeddings of the same @Embeddable type in one entity require @AttributeOverrides to rename the columns and avoid conflicts. @Embeddable classes must have a no-arg constructor and should implement equals/hashCode based on their fields (value equality).
Defining and Using @Embeddable
An Address value object embedded in both Customer and Order — the columns appear in each respective table, with no separate address table.
@Embeddable
public class Address {
@Column(nullable = false, length = 200)
private String street;
@Column(nullable = false, length = 100)
private String city;
@Column(nullable = false, length = 10)
private String postcode;
@Column(nullable = false, length = 2)
private String countryCode;
// no-arg constructor required
protected Address() {}
public Address(String street, String city, String postcode, String countryCode) {
this.street = street; this.city = city;
this.postcode = postcode; this.countryCode = countryCode;
}
// equals() and hashCode() based on all fields (value equality)
}
@Entity
public class Customer {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Embedded // columns: street, city, postcode, country_code
private Address billingAddress;
}@AttributeOverrides — Multiple Embeddings
If the same @Embeddable is embedded twice in one entity, you must override column names to avoid duplicates in the DDL.
@Entity
public class Order {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "street", column = @Column(name = "billing_street")),
@AttributeOverride(name = "city", column = @Column(name = "billing_city")),
@AttributeOverride(name = "postcode", column = @Column(name = "billing_postcode")),
@AttributeOverride(name = "countryCode", column = @Column(name = "billing_country"))
})
private Address billingAddress;
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "street", column = @Column(name = "shipping_street")),
@AttributeOverride(name = "city", column = @Column(name = "shipping_city")),
@AttributeOverride(name = "postcode", column = @Column(name = "shipping_postcode")),
@AttributeOverride(name = "countryCode", column = @Column(name = "shipping_country"))
})
private Address shippingAddress;
}Null Embeddable Handling
When an embedded object is null, Hibernate stores NULL for all its columns. On load, if all embedded columns are NULL, Hibernate returns null for the embedded field (optional behaviour configurable via @NotFound or @Embedded with optional handling).
// If shippingAddress is null in Java, all shipping_* columns are NULL in the row
// When loaded: all-NULL columns → Hibernate returns null for shippingAddress field
// Guard null before accessing embedded value
public String getShippingCity() {
return shippingAddress != null ? shippingAddress.getCity() : null;
}
// Or use Optional in service layer
Optional.ofNullable(order.getShippingAddress())
.map(Address::getCity)
.ifPresent(city -> log.info("Shipping to: {}", city));Key Points to Remember
- 1@Embeddable class columns are stored in the owning entity's table — no separate table or join
- 2Value types have no identity; use value equality (equals/hashCode on all fields)
- 3@AttributeOverrides is required when embedding the same type more than once in one entity
- 4A null @Embedded field stores all its columns as NULL; all-NULL columns load back as null
- 5@Embeddable classes need a no-arg constructor (can be protected/package-private)
- 6Embeddables can nest other embeddables — keep nesting shallow for readability
Interview Questions
Sign in to ask AriaWhat is the difference between @Embeddable and @Entity?
When do you need @AttributeOverrides and why?
How does Hibernate handle a null @Embedded field in the database?
What equals/hashCode strategy is correct for an @Embeddable class?
Can an @Embeddable class have relationships to other entities?
Ask Aria about @Embeddable & @Embedded
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.