Many small improvements
git-svn-id: https://svn.jboss.org/repos/hibernate/trunk/Hibernate3/doc@5366 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
7ca1999a26
commit
53343571c9
|
@ -1,7 +1,7 @@
|
|||
<chapter id="collections">
|
||||
<title>Collection Mapping</title>
|
||||
|
||||
<sect1 id="collections-persistent" revision="1">
|
||||
<sect1 id="collections-persistent" revision="2">
|
||||
<title>Persistent Collections</title>
|
||||
|
||||
<para>
|
||||
|
@ -27,20 +27,25 @@
|
|||
<para>
|
||||
Now the caveat: persistent collections do not retain any extra semantics added by the class
|
||||
implementing the collection interface (eg. iteration order of a <literal>LinkedHashSet</literal>).
|
||||
The persistent collections actually behave like
|
||||
The Java type of a property holding a collection must be the interface type: <literal>Map</literal>,
|
||||
<literal>Set</literal>, <literal>List</literal>, or simply <literal>Collection</literal>; never
|
||||
<literal>HashMap</literal>, <literal>TreeSet</literal> or <literal>ArrayList</literal>. This
|
||||
restriction exists because, when you're not looking, Hibernate sneakily replaces your instances
|
||||
of <literal>Map</literal>, <literal>Set</literal> and <literal>List</literal> with instances
|
||||
of its own persistent implementations of <literal>Map</literal>, <literal>Set</literal>, or
|
||||
<literal>List</literal>. (So also be careful when using <literal>==</literal> on your collections.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You may therefore initialize a collection in your class with whatever implementation
|
||||
you find compatible. The persistent collections injected by Hibernate behave like
|
||||
<literal>HashMap</literal>,
|
||||
<literal>HashSet</literal>,
|
||||
<literal>TreeMap</literal>,
|
||||
<literal>TreeSet</literal> and
|
||||
<literal>ArrayList</literal>
|
||||
respectively. Furthermore, the Java type of a property holding a collection must be
|
||||
the interface type (ie. <literal>Map</literal>, <literal>Set</literal> or
|
||||
<literal>List</literal>; never <literal>HashMap</literal>, <literal>TreeSet</literal> or
|
||||
<literal>ArrayList</literal>). This restriction exists because, when you're not looking,
|
||||
Hibernate sneakily replaces your instances of <literal>Map</literal>, <literal>Set</literal>
|
||||
and <literal>List</literal> with instances of its own persistent implementations of
|
||||
<literal>Map</literal>, <literal>Set</literal> or <literal>List</literal>. (So also be careful
|
||||
when using <literal>==</literal> on your collections.)
|
||||
respectively. Of course, this depends on the mapping style you chose (ie. ordered or
|
||||
not, preserving position of elements, allowing duplicates, etc).
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[Cat cat = new DomesticCat();
|
||||
|
@ -50,12 +55,12 @@ Set kittens = new HashSet();
|
|||
kittens.add(kitten);
|
||||
cat.setKittens(kittens);
|
||||
session.save(cat);
|
||||
kittens = cat.getKittens(); //Okay, kittens collection is a Set
|
||||
(HashSet) cat.getKittens(); //Error!]]></programlisting>
|
||||
kittens = cat.getKittens(); // Okay, kittens collection is a Set
|
||||
(HashSet) cat.getKittens(); // Error!]]></programlisting>
|
||||
|
||||
<para>
|
||||
Collections obey the usual rules for value types: no shared
|
||||
references, created and deleted along with containing entity. Due to the underlying
|
||||
Collections (not the contents) obey the usual rules for value types: no shared
|
||||
references, created and deleted along with the owning entity. Due to the underlying
|
||||
relational model, they do not support null value semantics; Hibernate does not
|
||||
distinguish between a null collection reference and an empty collection.
|
||||
</para>
|
||||
|
@ -73,36 +78,41 @@ kittens = cat.getKittens(); //Okay, kittens collection is a Set
|
|||
<para>
|
||||
Collection instances are distinguished in the database by a foreign key to
|
||||
the owning entity. This foreign key is referred to as the
|
||||
<emphasis>collection key </emphasis>. The collection key is mapped by
|
||||
the <literal><key></literal> element. If you have a foreign-key constraint
|
||||
set in the database, and have chosen the <literal>ON DELETE CASCADE</literal>
|
||||
option, always use the <literal>on-delete</literal> attribute on your
|
||||
<literal><key></literal> mappings:
|
||||
<emphasis>collection key </emphasis>, on the table holding the collection elements.
|
||||
The collection key is mapped by the <literal><key></literal> element. If you
|
||||
have a foreign-key constraint set in the database, and have chosen the
|
||||
<literal>ON DELETE CASCADE</literal> option, always use the
|
||||
<literal>on-delete</literal> attribute on your <literal><key></literal>
|
||||
mappings:
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[<key column="CHILD_ID" on-delete="cascade"/>]]></programlisting>
|
||||
|
||||
<para>
|
||||
Collections may contain almost any other Hibernate type, including all basic types,
|
||||
custom types, entity types and components. This is an important definition: An object
|
||||
in a collection can either be handled with "pass by value" semantics (it therefore
|
||||
fully depends on the collection owner) or it can be a reference to another entity
|
||||
with an own lifecycle. Collections may not contain other collections. The contained type
|
||||
custom types, components, and of course, references to other entities. This is an
|
||||
important definition: An object in a collection can either be handled with "pass by
|
||||
value" semantics (it therefore fully depends on the collection owner) or it can be a
|
||||
reference to another entity, with its own lifecycle. In this case, only the "link"
|
||||
between two objects is stored in the collection (non-Java developers call these links
|
||||
"pointers"). Collections may not contain other collections. The contained type
|
||||
is referred to as the <emphasis>collection element type</emphasis>. Collection elements
|
||||
are mapped by <literal><element></literal>, <literal><composite-element></literal>,
|
||||
<literal><one-to-many></literal>, <literal><many-to-many></literal> or
|
||||
<literal><many-to-any></literal>. The first two map elements with value semantics,
|
||||
the other three are used to map entity associations.
|
||||
or in the case of entity references, with <literal><one-to-many></literal>,
|
||||
<literal><many-to-many></literal>, or <literal><many-to-any></literal>.
|
||||
The first two map elements with value semantics, the other three are used to map
|
||||
entity associations.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
All collection types except <literal>Set</literal> and bag have an <emphasis>index
|
||||
</emphasis> column - a column that maps to an array or <literal>List</literal> index or
|
||||
<literal>Map</literal> key. The index of a <literal>Map</literal> may be of any
|
||||
basic type, an entity type or even a composite type (it may not be a collection). The
|
||||
index of an array or list is always of type <literal>integer</literal>. Indexes are
|
||||
mapped using <literal><index></literal>, <literal><index-many-to-many></literal>,
|
||||
<literal><composite-index></literal> or <literal><index-many-to-any></literal>.
|
||||
All collection mappings, except those with set and bag semantics, need an
|
||||
<emphasis>index</emphasis> column in the collection table - a column that maps to an
|
||||
array index, or <literal>List</literal> index, or <literal>Map</literal> key. The
|
||||
index of a <literal>Map</literal> may be of any basic type, it may be an entity reference,
|
||||
or even a composite type (it may not be a collection). The index of an array or list is
|
||||
always of type <literal>integer</literal>. Indexes are mapped using
|
||||
<literal><index></literal>, <literal><index-many-to-many></literal>,
|
||||
<literal><composite-index></literal>, or <literal><index-many-to-any></literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -270,7 +280,7 @@ kittens = cat.getKittens(); //Okay, kittens collection is a Set
|
|||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="collections-ofvalues">
|
||||
<sect1 id="collections-ofvalues" revision="1">
|
||||
<title>Collections of Values and Many-To-Many Associations</title>
|
||||
|
||||
<para>
|
||||
|
@ -390,9 +400,8 @@ kittens = cat.getKittens(); //Okay, kittens collection is a Set
|
|||
</programlistingco>
|
||||
|
||||
<para>
|
||||
A collection of entities with its own table corresponds to the relational notion
|
||||
of <emphasis>many-to-many association</emphasis>. A many to many association is the
|
||||
most natural mapping of a Java collection but is not usually the best relational model.
|
||||
A collection of entity references, where the references are held in a separate table
|
||||
corresponds to the relational notion of <emphasis>many-to-many association</emphasis>.
|
||||
</para>
|
||||
|
||||
<programlistingco>
|
||||
|
@ -404,7 +413,7 @@ kittens = cat.getKittens(); //Okay, kittens collection is a Set
|
|||
<programlisting><![CDATA[<many-to-many
|
||||
column="column_name"
|
||||
class="ClassName"
|
||||
outer-join="true|false|auto"
|
||||
fetch="select|join"
|
||||
/>]]></programlisting>
|
||||
<calloutlist>
|
||||
<callout arearefs="manytomany1">
|
||||
|
@ -419,9 +428,13 @@ kittens = cat.getKittens(); //Okay, kittens collection is a Set
|
|||
</callout>
|
||||
<callout arearefs="manytomany3">
|
||||
<para>
|
||||
<literal>outer-join</literal> (optional - defaults to <literal>auto</literal>):
|
||||
enables outer-join fetching for this association when
|
||||
<literal>hibernate.use_outer_join</literal> is set.
|
||||
<literal>fetch</literal> (optional - defaults to <literal>join</literal>):
|
||||
enables outer-join or sequential select fetching for this association. This
|
||||
is a special case, for full eager fetching (in a single <literal>SELECT</literal>)
|
||||
of an entity and its many-to-many relationships to other entities, you would
|
||||
enable <literal>join</literal> fetching not only of the collection itself,
|
||||
but also with this attribute on the <literal><many-to-many></literal>
|
||||
nested element.
|
||||
</para>
|
||||
</callout>
|
||||
</calloutlist>
|
||||
|
@ -566,7 +579,7 @@ kittens = cat.getKittens(); //Okay, kittens collection is a Set
|
|||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="collections-sorted" revision="1">
|
||||
<sect1 id="collections-sorted" revision="2">
|
||||
<title>Sorted Collections</title>
|
||||
|
||||
<para>
|
||||
|
@ -605,7 +618,7 @@ kittens = cat.getKittens(); //Okay, kittens collection is a Set
|
|||
memory.
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[<set name="aliases" table="person_aliases" order-by="name asc">
|
||||
<programlisting><![CDATA[<set name="aliases" table="person_aliases" order-by="lower(name) asc">
|
||||
<key column="person"/>
|
||||
<element column="name" type="string"/>
|
||||
</set>
|
||||
|
@ -678,7 +691,7 @@ kittens = cat.getKittens(); //Okay, kittens collection is a Set
|
|||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="collections-bidirectional">
|
||||
<sect1 id="collections-bidirectional" revision="1">
|
||||
<title>Bidirectional Associations</title>
|
||||
|
||||
<para>
|
||||
|
@ -716,9 +729,13 @@ kittens = cat.getKittens(); //Okay, kittens collection is a Set
|
|||
<para>
|
||||
You may specify a bidirectional many-to-many association simply by mapping two
|
||||
many-to-many associations to the same database table and declaring one end as
|
||||
<emphasis>inverse</emphasis> (which one is your choice). Here's an example of
|
||||
a bidirectional many-to-many association from a class back to <emphasis>itself</emphasis>
|
||||
(each category can have many items and each item can be in many categories):
|
||||
<emphasis>inverse</emphasis> (which one is your choice, but it can not be an
|
||||
indexed collection).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here's an example of a bidirectional many-to-many association; each category can
|
||||
have many items and each item can be in many categories:
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[<class name="org.hibernate.auction.Category">
|
||||
|
@ -753,18 +770,18 @@ kittens = cat.getKittens(); //Okay, kittens collection is a Set
|
|||
category.getItems().add(item); // The category now "knows" about the relationship
|
||||
item.getCategories().add(category); // The item now "knows" about the relationship
|
||||
|
||||
session.update(item); // No effect, nothing will be saved!
|
||||
session.update(category); // The relationship will be saved]]></programlisting>
|
||||
session.create(item); // The relationship won't be saved!
|
||||
session.create(category); // The relationship will be saved]]></programlisting>
|
||||
|
||||
<para>
|
||||
The non-inverse side is used to save the in-memory representation to the database.
|
||||
We would get an unneccessary INSERT/UPDATE and probably even a foreign key violation
|
||||
if both would trigger changes! The same is of course also true for bidirectional
|
||||
one-to-many associations.
|
||||
if both would trigger changes!
|
||||
</para>
|
||||
|
||||
<para>
|
||||
You may map a bidirectional one-to-many association by mapping a one-to-many association
|
||||
The same is of course also true for bidirectional one-to-many associations. You may
|
||||
map a bidirectional one-to-many association by mapping a one-to-many association
|
||||
to the same table column(s) as a many-to-one association and declaring the many-valued
|
||||
end <literal>inverse="true"</literal>.
|
||||
</para>
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
<title>Dependent objects</title>
|
||||
|
||||
<para>
|
||||
A component is a contained object that is persisted as a value type, not an entity.
|
||||
The term "component" refers to the object-oriented notion of composition
|
||||
A component is a contained object that is persisted as a value type, not an entity
|
||||
reference. The term "component" refers to the object-oriented notion of composition
|
||||
(not to architecture-level components). For example, you might model a person like this:
|
||||
</para>
|
||||
|
||||
|
@ -97,10 +97,12 @@
|
|||
</para>
|
||||
|
||||
<para>
|
||||
Like all value types, components do not support shared references. The null
|
||||
value semantics of a component are <emphasis>ad hoc</emphasis>. When reloading the
|
||||
containing object, Hibernate will assume that if all component columns are
|
||||
null, then the entire component is null. This should be okay for most purposes.
|
||||
Like all 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 ojects, only "the same" by value. The null value semantics of a component are
|
||||
<emphasis>ad hoc</emphasis>. When reloading the containing object, Hibernate will assume
|
||||
that if all component columns are null, then the entire component is null. This should
|
||||
be okay for most purposes.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -131,7 +133,7 @@
|
|||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="components-incollections">
|
||||
<sect1 id="components-incollections" revision="1">
|
||||
<title>Collections of dependent objects</title>
|
||||
|
||||
<para>
|
||||
|
@ -202,6 +204,14 @@
|
|||
</set>
|
||||
</class>]]></programlisting>
|
||||
|
||||
<para>
|
||||
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 <literal>Purchase</literal> can be in the
|
||||
set of an <literal>Order</literal>, but it can't be referenced by the <literal>Item</literal>
|
||||
at the same time.
|
||||
</para>
|
||||
|
||||
<para>Even ternary (or quaternary, etc) associations are possible:</para>
|
||||
|
||||
<programlisting><![CDATA[<class name="eg.Order" .... >
|
||||
|
@ -268,6 +278,10 @@
|
|||
previous session.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
TODO: document new auto-detect features for assigned IDs in H3
|
||||
</para>
|
||||
|
||||
<para>
|
||||
So, if you wish to use transitive reattachment (you don't have to), you must
|
||||
either implement <literal>Interceptor.isUnsaved()</literal> or define the
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
<sect1 id="inheritance-strategies" revision="2">
|
||||
<title>The Three Strategies</title>
|
||||
|
||||
<para>
|
||||
TODO: While this is all still supported, many new features would require
|
||||
a rewrite of this whole chapter
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Hibernate supports the three basic inheritance mapping strategies.
|
||||
</para>
|
||||
|
|
Loading…
Reference in New Issue