Collections of components are supported (eg. an array of type
Name
). Declare your component collection by
replacing the <element>
tag with a
<composite-element>
tag.
<set name="someNames" table="some_names" lazy="true"> <key column="id"/> <composite-element class="eg.Name"> <!-- class attribute required --> <property name="initial"/> <property name="first"/> <property name="last"/> </composite-element> </set>
Note: if you define a Set
of composite elements, it is
very important to implement equals()
and
hashCode()
correctly.
Composite elements may contain components but not collections. If your
composite element itself contains
components, use the <nested-composite-element>
tag. This is a pretty exotic case - a collection of components which
themselves have components. By this stage you should be asking yourself
if a one-to-many association is more appropriate. Try remodelling the
composite element as an entity - but note that even though the Java model
is the same, the relational model and persistence semantics are still
slightly different.
Please note that a composite element mapping doesn't support null-able properties
if you're using a <set>
. Hibernate
has to use each columns value to identify a record when deleting objects
(there is no separate primary key column in the composite element table),
which is not possible with null values. You have to either use only
not-null properties in a composite-element or choose a
<list>
, <map>
,
<bag>
or <idbag>
.
A special case of a composite element is a composite element with a nested
<many-to-one>
element. A mapping like this allows
you to map extra columns of a many-to-many association table to the
composite element class. The following is a many-to-many association
from Order
to Item
where
purchaseDate
, price
and
quantity
are properties of the association:
<class name="eg.Order" .... > .... <set name="purchasedItems" table="purchase_items" lazy="true"> <key column="order_id"> <composite-element class="eg.Purchase"> <property name="purchaseDate"/> <property name="price"/> <property name="quantity"/> <many-to-one name="item" class="eg.Item"/> <!-- class attribute is optional --> </composite-element> </set> </class>
Of course, there can't be a reference to the purchae on the other side, for
bidirectional association navigation. Remember that components are value types and
don't allow shared references. A single Purchase
can be in the
set of an Order
, but it can't be referenced by the Item
at the same time.
Even ternary (or quaternary, etc) associations are possible:
<class name="eg.Order" .... > .... <set name="purchasedItems" table="purchase_items" lazy="true"> <key column="order_id"> <composite-element class="eg.OrderLine"> <many-to-one name="purchaseDetails class="eg.Purchase"/> <many-to-one name="item" class="eg.Item"/> </composite-element> </set> </class>
Composite elements may appear in queries using the same syntax as associations to other entities.