|
Hibernate example source code file (component_mapping.xml)
This example Hibernate source code file (component_mapping.xml) is included in the DevDaily.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.
The Hibernate component_mapping.xml source code
<?xml version='1.0' encoding="UTF-8"?>
<!--
~ Hibernate, Relational Persistence for Idiomatic Java
~
~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
~ indicated by the @author tags or express copyright attribution
~ statements applied by the authors. All third-party contributions are
~ distributed under license by Red Hat Middleware LLC.
~
~ This copyrighted material is made available to anyone wishing to use, modify,
~ copy, or redistribute it subject to the terms and conditions of the GNU
~ Lesser General Public License, as published by the Free Software Foundation.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
~ for more details.
~
~ You should have received a copy of the GNU Lesser General Public License
~ along with this distribution; if not, write to:
~ Free Software Foundation, Inc.
~ 51 Franklin Street, Fifth Floor
~ Boston, MA 02110-1301 USA
-->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "../HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent">
%BOOK_ENTITIES;
]>
<chapter id="components">
<title>Component Mapping
<para>
The notion of a <emphasis>component is re-used in several different contexts and purposes
throughout Hibernate.
</para>
<section id="components-dependentobjects" revision="2" >
<title>Dependent objects
<para>
A component is a contained object that is persisted as a value type and not an entity
reference. The term "component" refers to the object-oriented notion of composition
and not to architecture-level components. For example, you can model a person like this:
</para>
<programlisting role="JAVA">
<programlisting role="JAVA">
<para>
Now <literal>Name can be persisted as a component of
<literal>Person. Name defines getter
and setter methods for its persistent properties, but it does not need to declare
any interfaces or identifier properties.
</para>
<para>
Our Hibernate mapping would look like this:
</para>
<programlisting role="XML">
<id name="Key" column="pid" type="string">
<generator class="uuid"/>
</id>
<property name="birthday" type="date"/>
<component name="Name" class="eg.Name">
<property name="initial"/>
<property name="first"/>
<property name="last"/>
</component>
</class>]]>
<para>
The person table would have the columns <literal>pid,
<literal>birthday,
<literal>initial,
<literal>first and
<literal>last.
</para>
<para>
Like value types, components do not support shared references. In other words, two
persons could have the same name, but the two person objects would contain two independent
name objects that were only "the same" by value. The null value semantics of a component are
<emphasis>ad hoc. When reloading the containing object, Hibernate will assume
that if all component columns are null, then the entire component is null. This is suitable for most purposes.
</para>
<para>
The properties of a component can be of any Hibernate type (collections, many-to-one
associations, other components, etc). Nested components should <emphasis>not
be considered an exotic usage. Hibernate is intended to support a fine-grained
object model.
</para>
<para>
The <literal><component> element allows a <parent>
subelement that maps a property of the component class as a reference back to the
containing entity.
</para>
<programlisting role="XML">
<id name="Key" column="pid" type="string">
<generator class="uuid"/>
</id>
<property name="birthday" type="date"/>
<component name="Name" class="eg.Name" unique="true">
<parent name="namedPerson"/>
<property name="initial"/>
<property name="first"/>
<property name="last"/>
</component>
</class>]]>
</section>
<section id="components-incollections" revision="1">
<title>Collections of dependent objects
<para>
Collections of components are supported (e.g. an array of type
<literal>Name). Declare your component collection by
replacing the <literal><element> tag with a
<literal><composite-element> tag:
</para>
<programlisting role="XML">
<key column="id"/>
<composite-element class="eg.Name">
<property name="initial"/>
<property name="first"/>
<property name="last"/>
</composite-element>
</set>]]>
<important>
<para>
If you define a <literal>Set of composite elements, it is
important to implement <literal>equals() and
<literal>hashCode() correctly.
</para>
</important>
<para>
Composite elements can contain components but not collections. If your
composite element contains
components, use the <literal><nested-composite-element>
tag. This case is a collection of components which
themselves have components. You may want to consider if
a one-to-many association is more appropriate. Remodel the
composite element as an entity, but be aware that even though the Java model
is the same, the relational model and persistence semantics are still
slightly different.
</para>
<para>
A composite element mapping does not support null-able properties
if you are using a <literal><set>. There is no separate primary key column
in the composite element table. Hibernate
uses each column's value to identify a record when deleting objects,
which is not possible with null values. You have to either use only
not-null properties in a composite-element or choose a
<literal><list>, <map>,
<literal><bag> or <idbag>.
</para>
<para>
A special case of a composite element is a composite element with a nested
<literal><many-to-one> element. This mapping 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 <literal>Order to Item, where
<literal>purchaseDate, price and
<literal>quantity are properties of the association:
</para>
<programlisting role="XML">
....
<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"/>
</composite-element>
</set>
</class>]]>
<para>
There cannot be a reference to the purchase on the other side for
bidirectional association navigation. Components are value types and
do not allow shared references. A single <literal>Purchase can be in the
set of an <literal>Order, but it cannot be referenced by the Item
at the same time.
</para>
<para>Even ternary (or quaternary, etc) associations are possible:
<programlisting role="XML">
....
<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>]]>
<para>
Composite elements can appear in queries using the same syntax as
associations to other entities.
</para>
</section>
<section id="components-asmapindex">
<title>Components as Map indices
<para>
The <literal><composite-map-key> element allows you to map a
component class as the key of a <literal>Map. Ensure that you override
<literal>hashCode() and equals() correctly on
the component class.
</para>
</section>
<section id="components-compositeid" revision="1">
<title>Components as composite identifiers
<para>
You can use a component as an identifier of an entity class. Your component
class must satisfy certain requirements:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
It must implement <literal>java.io.Serializable.
</para>
</listitem>
<listitem>
<para>
It must re-implement <literal>equals() and
<literal>hashCode() consistently with the database's
notion of composite key equality.
</para>
</listitem>
</itemizedlist>
<note>
<title>Note
<para>
In Hibernate3, although the second requirement is not an absolutely hard
requirement of Hibernate, it is recommended.
</para>
</note>
<para>
You cannot use an <literal>IdentifierGenerator to generate composite keys.
Instead the application must assign its own identifiers.
</para>
<para>
Use the <literal><composite-id> tag, with nested
<literal><key-property> elements, in place of the usual
<literal><id> declaration. For example, the
<literal>OrderLine class has a primary key that depends upon
the (composite) primary key of <literal>Order.
</para>
<programlisting role="XML">
<composite-id name="id" class="OrderLineId">
<key-property name="lineId"/>
<key-property name="orderId"/>
<key-property name="customerId"/>
</composite-id>
<property name="name"/>
<many-to-one name="order" class="Order"
insert="false" update="false">
<column name="orderId"/>
<column name="customerId"/>
</many-to-one>
....
</class>]]>
<para>
Any foreign keys referencing the <literal>OrderLine table are now
composite. Declare this in your mappings for other classes. An association
to <literal>OrderLine is mapped like this:
</para>
<programlisting role="XML">
<!-- the "class" attribute is optional, as usual -->
<column name="lineId"/>
<column name="orderId"/>
<column name="customerId"/>
</many-to-one>]]>
<tip>
<para>
The <literal>column element is an alternative to the
<literal>column attribute everywhere. Using the
<literal>column element just gives more declaration
options, which are mostly useful when utilizing
<literal>hbm2ddl
</para>
</tip>
<para>
A <literal>many-to-many association to OrderLine also
uses the composite foreign key:
</para>
<programlisting role="XML">
<key column name="warehouseId"/>
<many-to-many class="OrderLine">
<column name="lineId"/>
<column name="orderId"/>
<column name="customerId"/>
</many-to-many>
</set>]]>
<para>
The collection of <literal>OrderLines in Order would
use:
</para>
<programlisting role="XML">
<key>
<column name="orderId"/>
<column name="customerId"/>
</key>
<one-to-many class="OrderLine"/>
</set>]]>
<para>
The <literal><one-to-many> element declares no columns.
</para>
<para>
If <literal>OrderLine itself owns a collection, it also has a composite
foreign key.
</para>
<programlisting role="XML">
....
....
<list name="deliveryAttempts">
<key>
<column name="lineId"/>
<column name="orderId"/>
<column name="customerId"/>
</key>
<list-index column="attemptId" base="1"/>
<composite-element class="DeliveryAttempt">
...
</composite-element>
</set>
</class>]]>
</section>
<section id="components-dynamic" revision="1">
<title>Dynamic components
<para>
You can also map a property of type <literal>Map:
</para>
<programlisting role="XML">
<property name="foo" column="FOO" type="string"/>
<property name="bar" column="BAR" type="integer"/>
<many-to-one name="baz" class="Baz" column="BAZ_ID"/>
</dynamic-component>]]>
<para>
The semantics of a <literal><dynamic-component> mapping are identical
to <literal><component>. The advantage of this kind of mapping is
the ability to determine the actual properties of the bean at deployment time just
by editing the mapping document. Runtime manipulation of the mapping document is
also possible, using a DOM parser. You can also access, and change, Hibernate's
configuration-time metamodel via the <literal>Configuration object.
</para>
</section>
</chapter>
Other Hibernate examples (source code examples)
Here is a short list of links related to this Hibernate component_mapping.xml source code file:
|