Engineering Full Stack Apps with Java and JavaScript
We have already seen the definition and properties of an entity and value class in http://javajee.com/entities-and-value-types-in-hibernate-43. We will not see how we can actually embed a value type within an entity. We will also see how we can embed a collection inside an entity.
The simplest way to embed a value type in an entity class is to treat the member variables of the embedded class (e.g. Address), the same way as we treat the member variables of the embedding class (e.g. User) by adding more columns to the entity table one column each for the value type class members.
To embed a value type like this, we have to annotate the embedded class as @Embeddable and annotate the reference variable to the value type class in the embedding class as @Embedded.
Even though @Embedded is optional when you have @Embeddable, it is better to have them both.
There is a special case: @Embedded and @Id won’t work together.
To get the combined behavior of @Embedded and @Id, we should use @EmbeddedId annotation.
If you have a collection/list of value types like a list of addresses, hibernate will create a different table for the included collection/list and link that table to the original table using a foreign key.
For this you should use the @ElementCollection annotation over the collection/list declaration in the embeding entity class (instead of @Embedded).
You can also use the optional @JoinTable in addition to @ElementCollection, for instance, to give a name for the join column created for the foreign key.
By default it will be parentclassname_referencefield.
We can also use hibernate specific annotations such as @CollectionId, for instance, to define a primary key for the list table.
Example Usage: @ElementCollection
...
@ElementCollection
private Set<Address> AddressList = new HashSet<Address>();
...
Example Usage: @JoinTable
...
@ElementCollection
@JoinTable(name = "USE_ADDR_TABLE", joinColumns = @JoinColumn(name = "USER_ID_COL"))
private Set<Address> AddressList = new HashSet<Address>();
...
There might be situations where you would want to modify the attributes of the embedded class (eg. Address) within an embedding class (eg. User), for instance, changing the database column name for a field. You can do this within the embedded class itself. But what if you don’t have access to the embedded class or if you want different behavior for two different instances of the embedded class; you will have to override the embedded class behavior in the embedding class.
We can use @AttributeOverride annotation to override the details of a field of the embedded class and then enclose all such @AttributeOverride annotations inside @AttributeOverrides annotation.