357 lines
11 KiB
XML
357 lines
11 KiB
XML
<chapter id="example-mappings">
|
|
<title>Example: Various Mappings</title>
|
|
|
|
<para>
|
|
This chapters shows off some more complex association mappings.
|
|
</para>
|
|
|
|
<sect1 id="example-mappings-emp">
|
|
<title>Employer/Employee</title>
|
|
|
|
<para>
|
|
The following model of the relationship between <literal>Employer</literal> and
|
|
<literal>Employee</literal> uses an actual entity class (<literal>Employment</literal>)
|
|
to represent the association. This is done because there might be more than one
|
|
period of employment for the same two parties. Components are used to model monetory
|
|
values and employee names.
|
|
</para>
|
|
|
|
<mediaobject>
|
|
<imageobject role="fo">
|
|
<imagedata fileref="images/EmployerEmployee.gif" format="GIF" align="center"/>
|
|
</imageobject>
|
|
<imageobject role="html">
|
|
<imagedata fileref="../shared/images/EmployerEmployee.gif" format="GIF" align="center"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
|
|
<para>
|
|
Heres a possible mapping document:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<hibernate-mapping>
|
|
|
|
<class name="Employer" table="employers">
|
|
<id name="id">
|
|
<generator class="sequence">
|
|
<param name="sequence">employer_id_seq</param>
|
|
</generator>
|
|
</id>
|
|
<property name="name"/>
|
|
</class>
|
|
|
|
<class name="Employment" table="employment_periods">
|
|
|
|
<id name="id">
|
|
<generator class="sequence">
|
|
<param name="sequence">employment_id_seq</param>
|
|
</generator>
|
|
</id>
|
|
<property name="startDate" column="start_date"/>
|
|
<property name="endDate" column="end_date"/>
|
|
|
|
<component name="hourlyRate" class="MonetoryAmount">
|
|
<property name="amount">
|
|
<column name="hourly_rate" sql-type="NUMERIC(12, 2)"/>
|
|
</property>
|
|
<property name="currency" length="12"/>
|
|
</component>
|
|
|
|
<many-to-one name="employer" column="employer_id" not-null="true"/>
|
|
<many-to-one name="employee" column="employee_id" not-null="true"/>
|
|
|
|
</class>
|
|
|
|
<class name="Employee" table="employees">
|
|
<id name="id">
|
|
<generator class="sequence">
|
|
<param name="sequence">employee_id_seq</param>
|
|
</generator>
|
|
</id>
|
|
<property name="taxfileNumber"/>
|
|
<component name="name" class="Name">
|
|
<property name="firstName"/>
|
|
<property name="initial"/>
|
|
<property name="lastName"/>
|
|
</component>
|
|
</class>
|
|
|
|
</hibernate-mapping>]]></programlisting>
|
|
|
|
<para>
|
|
And heres the table schema generated by <literal>SchemaExport</literal>.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[create table employers (
|
|
id BIGINT not null,
|
|
name VARCHAR(255),
|
|
primary key (id)
|
|
)
|
|
|
|
create table employment_periods (
|
|
id BIGINT not null,
|
|
hourly_rate NUMERIC(12, 2),
|
|
currency VARCHAR(12),
|
|
employee_id BIGINT not null,
|
|
employer_id BIGINT not null,
|
|
end_date TIMESTAMP,
|
|
start_date TIMESTAMP,
|
|
primary key (id)
|
|
)
|
|
|
|
create table employees (
|
|
id BIGINT not null,
|
|
firstName VARCHAR(255),
|
|
initial CHAR(1),
|
|
lastName VARCHAR(255),
|
|
taxfileNumber VARCHAR(255),
|
|
primary key (id)
|
|
)
|
|
|
|
alter table employment_periods
|
|
add constraint employment_periodsFK0 foreign key (employer_id) references employers
|
|
alter table employment_periods
|
|
add constraint employment_periodsFK1 foreign key (employee_id) references employees
|
|
create sequence employee_id_seq
|
|
create sequence employment_id_seq
|
|
create sequence employer_id_seq]]></programlisting>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="example-mappings-authorwork">
|
|
<title>Author/Work</title>
|
|
|
|
<para>
|
|
Consider the following model of the relationships between <literal>Work</literal>,
|
|
<literal>Author</literal> and <literal>Person</literal>. We represent the relationship
|
|
between <literal>Work</literal> and <literal>Author</literal> as a many-to-many
|
|
association. We choose to represent the relationship between <literal>Author</literal>
|
|
and <literal>Person</literal> as one-to-one association. Another possibility would be to
|
|
have <literal>Author</literal> extend <literal>Person</literal>.
|
|
</para>
|
|
|
|
<mediaobject>
|
|
<imageobject role="fo">
|
|
<imagedata fileref="images/AuthorWork.gif" format="GIF" align="center"/>
|
|
</imageobject>
|
|
<imageobject role="html">
|
|
<imagedata fileref="../shared/images/AuthorWork.gif" format="GIF" align="center"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
|
|
<para>
|
|
The following mapping document correctly represents these relationships:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<hibernate-mapping>
|
|
|
|
<class name="Work" table="works" discriminator-value="W">
|
|
|
|
<id name="id" column="id">
|
|
<generator class="native"/>
|
|
</id>
|
|
<discriminator column="type" type="character"/>
|
|
|
|
<property name="title"/>
|
|
<set name="authors" table="author_work" lazy="true">
|
|
<key>
|
|
<column name="work_id" not-null="true"/>
|
|
</key>
|
|
<many-to-many class="Author">
|
|
<column name="author_id" not-null="true"/>
|
|
</many-to-many>
|
|
</set>
|
|
|
|
<subclass name="Book" discriminator-value="B">
|
|
<property name="text"/>
|
|
</subclass>
|
|
|
|
<subclass name="Song" discriminator-value="S">
|
|
<property name="tempo"/>
|
|
<property name="genre"/>
|
|
</subclass>
|
|
|
|
</class>
|
|
|
|
<class name="Author" table="authors">
|
|
|
|
<id name="id" column="id">
|
|
<!-- The Author must have the same identifier as the Person -->
|
|
<generator class="assigned"/>
|
|
</id>
|
|
|
|
<property name="alias"/>
|
|
<one-to-one name="person" constrained="true"/>
|
|
|
|
<set name="works" table="author_work" inverse="true" lazy="true">
|
|
<key column="author_id"/>
|
|
<many-to-many class="Work" column="work_id"/>
|
|
</set>
|
|
|
|
</class>
|
|
|
|
<class name="Person" table="persons">
|
|
<id name="id" column="id">
|
|
<generator class="native"/>
|
|
</id>
|
|
<property name="name"/>
|
|
</class>
|
|
|
|
</hibernate-mapping>]]></programlisting>
|
|
|
|
<para>
|
|
There are four tables in this mapping. <literal>works</literal>,
|
|
<literal>authors</literal> and <literal>persons</literal> hold work, author
|
|
and person data respectively. <literal>author_work</literal> is an association
|
|
table linking authors to works. Heres the table schema, as generated by
|
|
<literal>SchemaExport</literal>.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[create table works (
|
|
id BIGINT not null generated by default as identity,
|
|
tempo FLOAT,
|
|
genre VARCHAR(255),
|
|
text INTEGER,
|
|
title VARCHAR(255),
|
|
type CHAR(1) not null,
|
|
primary key (id)
|
|
)
|
|
|
|
create table author_work (
|
|
author_id BIGINT not null,
|
|
work_id BIGINT not null,
|
|
primary key (work_id, author_id)
|
|
)
|
|
|
|
create table authors (
|
|
id BIGINT not null generated by default as identity,
|
|
alias VARCHAR(255),
|
|
primary key (id)
|
|
)
|
|
|
|
create table persons (
|
|
id BIGINT not null generated by default as identity,
|
|
name VARCHAR(255),
|
|
primary key (id)
|
|
)
|
|
|
|
alter table authors
|
|
add constraint authorsFK0 foreign key (id) references persons
|
|
alter table author_work
|
|
add constraint author_workFK0 foreign key (author_id) references authors
|
|
alter table author_work
|
|
add constraint author_workFK1 foreign key (work_id) references works]]></programlisting>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="example-mappings-customerorderproduct">
|
|
<title>Customer/Order/Product</title>
|
|
|
|
<para>
|
|
Now consider a model of the relationships between <literal>Customer</literal>,
|
|
<literal>Order</literal> and <literal>LineItem</literal> and <literal>Product</literal>.
|
|
There is a one-to-many association between <literal>Customer</literal> and
|
|
<literal>Order</literal>, but how should we represent <literal>Order</literal> /
|
|
<literal>LineItem</literal> / <literal>Product</literal>? I've chosen to map
|
|
<literal>LineItem</literal> as an association class representing the many-to-many
|
|
association between <literal>Order</literal> and <literal>Product</literal>. In
|
|
Hibernate, this is called a composite element.
|
|
</para>
|
|
|
|
<mediaobject>
|
|
<imageobject role="fo">
|
|
<imagedata fileref="images/CustomerOrderProduct.gif" format="GIF" align="center"/>
|
|
</imageobject>
|
|
<imageobject role="html">
|
|
<imagedata fileref="../shared/images/CustomerOrderProduct.gif" format="GIF" align="center"/>
|
|
</imageobject>
|
|
</mediaobject>
|
|
|
|
<para>
|
|
The mapping document:
|
|
</para>
|
|
|
|
<programlisting><![CDATA[<hibernate-mapping>
|
|
|
|
<class name="Customer" table="customers">
|
|
<id name="id">
|
|
<generator class="native"/>
|
|
</id>
|
|
<property name="name"/>
|
|
<set name="orders" inverse="true" lazy="true">
|
|
<key column="customer_id"/>
|
|
<one-to-many class="Order"/>
|
|
</set>
|
|
</class>
|
|
|
|
<class name="Order" table="orders">
|
|
<id name="id">
|
|
<generator class="native"/>
|
|
</id>
|
|
<property name="date"/>
|
|
<many-to-one name="customer" column="customer_id"/>
|
|
<list name="lineItems" table="line_items" lazy="true">
|
|
<key column="order_id"/>
|
|
<index column="line_number"/>
|
|
<composite-element class="LineItem">
|
|
<property name="quantity"/>
|
|
<many-to-one name="product" column="product_id"/>
|
|
</composite-element>
|
|
</list>
|
|
</class>
|
|
|
|
<class name="Product" table="products">
|
|
<id name="id">
|
|
<generator class="native"/>
|
|
</id>
|
|
<property name="serialNumber"/>
|
|
</class>
|
|
|
|
</hibernate-mapping>]]></programlisting>
|
|
|
|
<para>
|
|
<literal>customers</literal>, <literal>orders</literal>, <literal>line_items</literal> and
|
|
<literal>products</literal> hold customer, order, order line item and product data
|
|
respectively. <literal>line_items</literal> also acts as an association table linking
|
|
orders with products.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[create table customers (
|
|
id BIGINT not null generated by default as identity,
|
|
name VARCHAR(255),
|
|
primary key (id)
|
|
)
|
|
|
|
create table orders (
|
|
id BIGINT not null generated by default as identity,
|
|
customer_id BIGINT,
|
|
date TIMESTAMP,
|
|
primary key (id)
|
|
)
|
|
|
|
create table line_items (
|
|
line_number INTEGER not null,
|
|
order_id BIGINT not null,
|
|
product_id BIGINT,
|
|
quantity INTEGER,
|
|
primary key (order_id, line_number)
|
|
)
|
|
|
|
create table products (
|
|
id BIGINT not null generated by default as identity,
|
|
serialNumber VARCHAR(255),
|
|
primary key (id)
|
|
)
|
|
|
|
alter table orders
|
|
add constraint ordersFK0 foreign key (customer_id) references customers
|
|
alter table line_items
|
|
add constraint line_itemsFK0 foreign key (product_id) references products
|
|
alter table line_items
|
|
add constraint line_itemsFK1 foreign key (order_id) references orders]]></programlisting>
|
|
|
|
</sect1>
|
|
|
|
</chapter>
|
|
|