Entities vs Value types
When we create domain model we must deal with two kinds of objects:
entities and value types. Entities represents objects that have some notion of
identity like person or a vehicle. Person may change name or even sex but we still use
the same object to represent that particular person, we only update object attributes
(e.g. even if I change my name I’m still myself).
Entities always have some kind of identifier that allows us to
distinguish them, this may be a
surrogate key like
Long id or
a natural key
like national id/social security number in case of person.
The other kind of objects that we encounter in domain model are value types. Value types represent things like addresses, phone numbers, money amounts, currencies etc. Value types are immutable and don’t need to have any identifier - two value types are equal if they contents are equal. If we need to update value type we just create a new instance of value type with updated attributes.
What this have to do with embeddable types?
In most cases embeddable types should be used to represent only value types
of your domain model.
Now let’s see the code!
Embeddable in Hibernate
We will start by creating
User entity that will have two embeddable value types
We don’t need to use any additional annotations to map embeddable types, we just declare them like any other field. Later we will see that we may change embeddable type mappings when needed.
Now let’s see how
PhoneNumber value type looks like.
Since it is our first value type I will present entire class:
First thing we should notice is that
PhoneNumber instances are immutable.
We can set
phoneNumber using constructor,
but we cannot change it.
Notice also that we overriden
provide value equality - two phone numbers are equal if they string
representations are equal.
To improve debugging experience we also overriden
The other class
MoneyAmount looks like this:
Notice that this class provides additional operations like
Because value types are immutable we cannot change already
MoneyAmount instance, instead we return a new object that
will represent result of the
Now let’s get to the Hibernate part.
Embeddable types must be marked with
they can contain one or more fields and every
field may carry
Embeddable types may contain other embeddable types,
but they cannot contain
When Hibernate stores embeddable types in database they are
stored in table of the entity that contains them.
For example for our
User entity Hibernate will generate table:
Sometimes we want to change e.g. one of the column names of the embeddable type
but only in certain containing type.
For example let’s say that we want to map
phone_number column. We may do this using
Unfortunately when we override column attributes we must redefine all of them, and syntax to do so it pretty verbose.
Now it’s time to save some ickle embeddables to database:
This operation will result in SQL:
We may also update embeddable type by providing new instance:
This will generate
Embeddable types and nullability
Hibernate stores null embeddable type as
NULL values in
all embeddable type columns. You can save object with
embeddable type only if all embeddable type columns are nullable.
When you try to do this with embeddable type that contains non-null
columns Hibernate will throw exception:
Sharing embeddable types between entities
Embeddable types follow value semantics, this means when we save the same instance of embeddable type in two different entities and then read back these entities we will get two instances of embeddable type:
This is generally not a problem because we should compare value types
Mapping many instances of embeddable type in the same entity
Let’s say we want to extend our
User entity to allow users to provide
second phone number. If we only add second
PhoneNumber field to the
Hibernate will not know how to name columns of the second
This will result in the exception:
We can easly fix this using
Collections of embeddable types
Embeddable types may be used as collection elements. Let’s extend our
so that user can have any number of phone numbers:
In this case collection elements are owned by entity class, if entity is removed all collection elements are removed as well. In database this will be represented by two tables:
Before you start using this method you must know how Hibernate will perform inserts/updates. Basically Hibernate first will remove all rows associated with given entity and then will perform many inserts (one insert per one collection element). This is horrible from performance point of view so use this mapping only with small collections.
Here is a bit of code to illustrate the point:
This will result in SQL:
Allowing duplicates in collection
If we want to allow duplicates in embeddable type collection we should map it as a bag:
This will result in database schema: Unfortunatelly this will not improve bad performance of embeddable type collections.
You can improve performance a bit (mainly with inserts) using
more informations can be found in these articles:
- StackOverflow: strange delete/insert behaviour
- How to Optimize Hibernate ElementCollection Statements
In this blog post I only scratched the surface of the embeddable types, there is more to learn about them. If you want to dig deeper I advice reading great book: Java Persistence with Hibernate 2nd.
Thats all for today, thanks for reading!