Mar 3, 2013 0
Mapping embeddable objects using multiple tables with JPA/Hibernate
I got recently into the situation in which my domain object, ProductData, which represents a product information on an e-commerce domain consists of many different conceptual fields within the same entity, however, these fields aren’t considered in a separate entity, since they cannot exist standalone without ProductData instance and they have no identity, at all. They’re actually properties of ProductData. Let’s consider the following example.
It is reasonable to map such a relationship using two different entities in ORM layer, but it’s not always the case that both parts of the relationship have got an identity (for example, it can be an auto-incremented value).
What about ER-Model ?
Maybe, you think that the two domain objects belong to the same table if we consider the entity relationship model. But, it sounds also reasonable to store the Configurations into an another table as they grow up. If you use a secondary table for Configurations, you can also map a collection of Configurations for a ProductData given. For one-to-one case, you can store the configuration as an embedded entity in the products table.
How to map ?
JPA’s “embeddable” concept is the solution for mapping of these unidentifiable and embeddable objects:
@Entity @Table(name="products") @SecondaryTable(name="configurations", pkJoinColumns=@PrimaryKeyJoinColumn(name="product_id")) public class ProductData { @Id @GeneratedValue private Long id; @Column(name="title") private String title; @Embedded @AttributeOverrides({ @AttributeOverride(name="url", column=@Column(name="url",table="configurations")), @AttributeOverride(name="autoSave", column=@Column(name="autosave", table="configurations")) }) private Configuration configuration; } @Embeddable public class Configuration { @Column(name="url") private URL url; @Column(name="autosave") private boolean autoSave; }
We’ve got now two different tables for two different objects which are linked through a foreign key, product_id. @Embedded annotation tells ORM provider that the embedded object does share the identity of the parent’s and it’s fields are merged with ProductData’s.
+--------+--------------+ +-----------------+-----------+--------------+
| id | title | | url | autosave | product_id |
+--------+--------------+ +-----------------+-----------+--------------+
| 1 | Test product | | http://test/ | 1 | 1 |
+--------+--------------+ +-----------------+-----------+--------------+
The embedded object’s fields are stored in a separated (secondary) table, which is defined within @SecondaryTable through @PrimaryKeyJoinColumn (We could embed it into the same table). @AttributeOverrides overrides mapping informations which are defined in @Embeddable.
I omitted the accessor method in the examples. If you want to the keep all informations in a single table instead of two different, just remove @SecondaryTable and explicit table definitions in @AttributeOverrides and add appropriate columns into the products table.



