HHH-3742 : documentation corrections

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@15831 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2009-01-29 20:06:25 +00:00
parent 4167921ea3
commit 4bd552cfdb
25 changed files with 2790 additions and 2744 deletions

View File

@ -33,7 +33,7 @@
<title>Overview</title>
<para>
A (very) high-level view of the Hibernate architecture:
The diagram below provides a high-level view of the Hibernate architecture:
</para>
<mediaobject>
@ -46,14 +46,18 @@
</mediaobject>
<para>
This diagram shows Hibernate using the database and configuration data to
provide persistence services (and persistent objects) to the application.
We do not have the scope in this document to provide a more detailed view of all the runtime architectures available;
Hibernate is flexible and supports several different approaches. We will, however,
show the two extremes: "minimal" architecture and "comprehensive" architecture.
</para>
<para>
This next diagram illustrates how Hibernate utilizes database and configuration data to
provide persistence services, and persistent objects, to the application.
</para>
<para>
We would like to show a more detailed view of the runtime architecture.
Unfortunately, Hibernate is flexible and supports several approaches. We will
show the two extremes. The "lite" architecture has the application
The "minimal" architecture has the application
provide its own JDBC connections and manage its own transactions. This approach
uses a minimal subset of Hibernate's APIs:
</para>
@ -68,8 +72,8 @@
</mediaobject>
<para>
The "full cream" architecture abstracts the application away from the
underlying JDBC/JTA APIs and lets Hibernate take care of the details.
The "comprehensive" architecture abstracts the application away from the
underlying JDBC/JTA APIs and allows Hibernate to manage the details.
</para>
<mediaobject>
@ -82,18 +86,18 @@
</mediaobject>
<para>
Heres some definitions of the objects in the diagrams:
Here are some definitions of the objects depicted in the diagrams:
<variablelist spacing="compact">
<varlistentry>
<term>SessionFactory (<literal>org.hibernate.SessionFactory</literal>)</term>
<listitem>
<para>
A threadsafe (immutable) cache of compiled mappings for a single database.
A threadsafe, immutable cache of compiled mappings for a single database.
A factory for <literal>Session</literal> and a client of
<literal>ConnectionProvider</literal>. Might hold an optional (second-level)
cache of data that is reusable between transactions, at a
process- or cluster-level.
<literal>ConnectionProvider</literal>, <literal>SessionFactory</literal> can hold an optional (second-level)
cache of data that is reusable between transactions at a
process, or cluster, level.
</para>
</listitem>
</varlistentry>
@ -102,9 +106,9 @@
<listitem>
<para>
A single-threaded, short-lived object representing a conversation between
the application and the persistent store. Wraps a JDBC connection. Factory
for <literal>Transaction</literal>. Holds a mandatory (first-level) cache
of persistent objects, used when navigating the object graph or looking up
the application and the persistent store. It wraps a JDBC connection and is a factory
for <literal>Transaction</literal>. <literal>Session</literal> holds a mandatory first-level cache
of persistent objects that are used when navigating the object graph or looking up
objects by identifier.
</para>
</listitem>
@ -114,10 +118,9 @@
<listitem>
<para>
Short-lived, single threaded objects containing persistent state and business
function. These might be ordinary JavaBeans/POJOs, the only special thing about
them is that they are currently associated with (exactly one)
<literal>Session</literal>. As soon as the <literal>Session</literal> is closed,
they will be detached and free to use in any application layer (e.g. directly
function. These can be ordinary JavaBeans/POJOs. They are associated with exactly one
<literal>Session</literal>. Once the <literal>Session</literal> is closed,
they will be detached and free to use in any application layer (for example, directly
as data transfer objects to and from presentation).
</para>
</listitem>
@ -128,7 +131,7 @@
<para>
Instances of persistent classes that are not currently associated with a
<literal>Session</literal>. They may have been instantiated by
the application and not (yet) persisted or they may have been instantiated by a
the application and not yet persisted, or they may have been instantiated by a
closed <literal>Session</literal>.
</para>
</listitem>
@ -138,11 +141,11 @@
<listitem>
<para>
(Optional) A single-threaded, short-lived object used by the application to
specify atomic units of work. Abstracts application from underlying JDBC,
specify atomic units of work. It abstracts the application from the underlying JDBC,
JTA or CORBA transaction. A <literal>Session</literal> might span several
<literal>Transaction</literal>s in some cases. However, transaction demarcation,
either using the underlying API or <literal>Transaction</literal>, is never
optional!
optional.
</para>
</listitem>
</varlistentry>
@ -150,9 +153,9 @@
<term>ConnectionProvider (<literal>org.hibernate.connection.ConnectionProvider</literal>)</term>
<listitem>
<para>
(Optional) A factory for (and pool of) JDBC connections. Abstracts application from
(Optional) A factory for, and pool of, JDBC connections. It abstracts the application from
underlying <literal>Datasource</literal> or <literal>DriverManager</literal>.
Not exposed to application, but can be extended/implemented by the developer.
It is not exposed to application, but it can be extended and/or implemented by the developer.
</para>
</listitem>
</varlistentry>
@ -160,8 +163,8 @@
<term>TransactionFactory (<literal>org.hibernate.TransactionFactory</literal>)</term>
<listitem>
<para>
(Optional) A factory for <literal>Transaction</literal> instances. Not exposed to the
application, but can be extended/implemented by the developer.
(Optional) A factory for <literal>Transaction</literal> instances. It is not exposed to the
application, but it can be extended and/or implemented by the developer.
</para>
</listitem>
</varlistentry>
@ -169,7 +172,7 @@
<term><emphasis>Extension Interfaces</emphasis></term>
<listitem>
<para>
Hibernate offers many optional extension interfaces you can implement to customize
Hibernate offers a range of optional extension interfaces you can implement to customize
the behavior of your persistence layer. See the API documentation for details.
</para>
</listitem>
@ -178,18 +181,18 @@
</para>
<para>
Given a "lite" architecture, the application bypasses the
Given a "minimal" architecture, the application bypasses the
<literal>Transaction</literal>/<literal>TransactionFactory</literal> and/or
<literal>ConnectionProvider</literal> APIs to talk to JTA or JDBC directly.
<literal>ConnectionProvider</literal> APIs to communicate with JTA or JDBC directly.
</para>
</sect1>
<sect1 id="architecture-states" revision="1">
<title>Instance states</title>
<para>
An instance of a persistent classes may be in one of three different states,
which are defined with respect to a <emphasis>persistence context</emphasis>.
The Hibernate <literal>Session</literal> object is the persistence context:
An instance of a persistent class can be in one of three different states. These states are
defined in relation to a <emphasis>persistence context</emphasis>.
The Hibernate <literal>Session</literal> object is the persistence context. The three different states are as follows:
</para>
<variablelist spacing="compact">
@ -197,9 +200,9 @@
<term>transient</term>
<listitem>
<para>
The instance is not, and has never been associated with
any persistence context. It has no persistent identity
(primary key value).
The instance is not associated with
any persistence context. It has no persistent identity or
primary key value.
</para>
</listitem>
</varlistentry>
@ -209,11 +212,11 @@
<para>
The instance is currently associated with a persistence
context. It has a persistent identity (primary key value)
and, perhaps, a corresponding row in the database. For a
and can have a corresponding row in the database. For a
particular persistence context, Hibernate
<emphasis>guarantees</emphasis> that persistent identity
is equivalent to Java identity (in-memory location of the
object).
is equivalent to Java identity in relation to the in-memory location of the
object.
</para>
</listitem>
</varlistentry>
@ -224,9 +227,9 @@
The instance was once associated with a persistence
context, but that context was closed, or the instance
was serialized to another process. It has a persistent
identity and, perhaps, a corresponding row in the database.
For detached instances, Hibernate makes no guarantees
about the relationship between persistent identity and
identity and can have a corresponding row in the database.
For detached instances, Hibernate does not guarantee
the relationship between persistent identity and
Java identity.
</para>
</listitem>
@ -238,36 +241,36 @@
<title>JMX Integration</title>
<para>
JMX is the J2EE standard for management of Java components. Hibernate may be managed via
a JMX standard service. We provide an MBean implementation in the distribution,
JMX is the J2EE standard for the management of Java components. Hibernate can be managed via
a JMX standard service. AN MBean implementation is provided in the distribution:
<literal>org.hibernate.jmx.HibernateService</literal>.
</para>
<para>
For an example how to deploy Hibernate as a JMX service on the JBoss Application Server,
please see the JBoss User Guide. On JBoss AS, you also get these benefits if you deploy
For an example of how to deploy Hibernate as a JMX service on the JBoss Application Server,
please see the JBoss User Guide. JBoss AS also provides these benefits if you deploy
using JMX:
</para>
<itemizedlist>
<listitem>
<para>
<emphasis>Session Management:</emphasis> The Hibernate <literal>Session</literal>'s life cycle
can be automatically bound to the scope of a JTA transaction. This means you no
longer have to manually open and close the <literal>Session</literal>, this
becomes the job of a JBoss EJB interceptor. You also don't have to worry about
transaction demarcation in your code anymore (unless you'd like to write a portable
persistence layer of course, use the optional Hibernate <literal>Transaction</literal>
<emphasis>Session Management</emphasis>: the Hibernate <literal>Session</literal>'s life cycle
can be automatically bound to the scope of a JTA transaction. This means that you no
longer have to manually open and close the <literal>Session</literal>; this
becomes the job of a JBoss EJB interceptor. You also do not have to worry about
transaction demarcation in your code (if you would like to write a portable
persistence layer use the optional Hibernate <literal>Transaction</literal>
API for this). You call the <literal>HibernateContext</literal> to access a
<literal>Session</literal>.
</para>
</listitem>
<listitem>
<para>
<emphasis>HAR deployment:</emphasis> Usually you deploy the Hibernate JMX service using a JBoss
service deployment descriptor (in an EAR and/or SAR file), it supports all the usual
<emphasis>HAR deployment</emphasis>: the Hibernate JMX service is deployed using a JBoss
service deployment descriptor in an EAR and/or SAR file, as it supports all the usual
configuration options of a Hibernate <literal>SessionFactory</literal>. However, you still
have to name all your mapping files in the deployment descriptor. If you decide to use
need to name all your mapping files in the deployment descriptor. If you use
the optional HAR deployment, JBoss will automatically detect all mapping files in your
HAR file.
</para>
@ -279,45 +282,45 @@
</para>
<para>
Another feature available as a JMX service are runtime Hibernate statistics. See
<xref linkend="configuration-optional-statistics"/>.
Another feature available as a JMX service is runtime Hibernate statistics. See
<xref linkend="configuration-optional-statistics"/> for more information.
</para>
</sect1>
<sect1 id="architecture-jca" revision="1">
<title>JCA Support</title>
<para>
Hibernate may also be configured as a JCA connector. Please see the website for more
details. Please note that Hibernate JCA support is still considered experimental.
Hibernate can also be configured as a JCA connector. Please see the website for more
information. Please note, however, that at this stage Hibernate JCA support is under development.
</para>
</sect1>
<sect1 id="architecture-current-session" revision="2">
<title>Contextual Sessions</title>
<title>Contextual sessions</title>
<para>
Most applications using Hibernate need some form of "contextual" sessions, where a given
Most applications using Hibernate need some form of "contextual" session, where a given
session is in effect throughout the scope of a given context. However, across applications
the definition of what constitutes a context is typically different; and different contexts
the definition of what constitutes a context is typically different; different contexts
define different scopes to the notion of current. Applications using Hibernate prior
to version 3.0 tended to utilize either home-grown <literal>ThreadLocal</literal>-based
contextual sessions, helper classes such as <literal>HibernateUtil</literal>, or utilized
third-party frameworks (such as Spring or Pico) which provided proxy/interception-based contextual sessions.
third-party frameworks, such as Spring or Pico, which provided proxy/interception-based contextual sessions.
</para>
<para>
Starting with version 3.0.1, Hibernate added the <literal>SessionFactory.getCurrentSession()</literal>
method. Initially, this assumed usage of <literal>JTA</literal> transactions, where the
method. Initially, this assumed usage of <literal>JTA</literal> transactions, where the
<literal>JTA</literal> transaction defined both the scope and context of a current session.
The Hibernate team maintains that, given the maturity of the numerous stand-alone
<literal>JTA TransactionManager</literal> implementations out there, most (if not all)
applications should be using <literal>JTA</literal> transaction management whether or not
Given the maturity of the numerous stand-alone
<literal>JTA TransactionManager</literal> implementations, most, if not all,
applications should be using <literal>JTA</literal> transaction management, whether or not
they are deployed into a <literal>J2EE</literal> container. Based on that, the
<literal>JTA</literal>-based contextual sessions is all you should ever need to use.
<literal>JTA</literal>-based contextual sessions are all you need to use.
</para>
<para>
However, as of version 3.1, the processing behind
<literal>SessionFactory.getCurrentSession()</literal> is now pluggable. To that
end, a new extension interface (<literal>org.hibernate.context.CurrentSessionContext</literal>)
and a new configuration parameter (<literal>hibernate.current_session_context_class</literal>)
end, a new extension interface, <literal>org.hibernate.context.CurrentSessionContext</literal>,
and a new configuration parameter, <literal>hibernate.current_session_context_class</literal>,
have been added to allow pluggability of the scope and context of defining current sessions.
</para>
<para>
@ -325,13 +328,13 @@
interface for a detailed discussion of its contract. It defines a single method,
<literal>currentSession()</literal>, by which the implementation is responsible for
tracking the current contextual session. Out-of-the-box, Hibernate comes with three
implementations of this interface.
implementations of this interface:
</para>
<itemizedlist>
<listitem>
<para>
<literal>org.hibernate.context.JTASessionContext</literal> - current sessions
<literal>org.hibernate.context.JTASessionContext</literal>: current sessions
are tracked and scoped by a <literal>JTA</literal> transaction. The processing
here is exactly the same as in the older JTA-only approach. See the Javadocs
for details.
@ -339,41 +342,41 @@
</listitem>
<listitem>
<para>
<literal>org.hibernate.context.ThreadLocalSessionContext</literal> - current
sessions are tracked by thread of execution. Again, see the Javadocs for details.
<literal>org.hibernate.context.ThreadLocalSessionContext</literal>:current
sessions are tracked by thread of execution. See the Javadocs for details.
</para>
</listitem>
<listitem>
<para>
<literal>org.hibernate.context.ManagedSessionContext</literal> - current
<literal>org.hibernate.context.ManagedSessionContext</literal>: current
sessions are tracked by thread of execution. However, you are responsible to
bind and unbind a <literal>Session</literal> instance with static methods
on this class, it does never open, flush, or close a <literal>Session</literal>.
on this class: it does not open, flush, or close a <literal>Session</literal>.
</para>
</listitem>
</itemizedlist>
<para>
The first two implementations provide a "one session - one database transaction" programming
model, also known and used as <emphasis>session-per-request</emphasis>. The beginning
model. This is also also known and used as <emphasis>session-per-request</emphasis>. The beginning
and end of a Hibernate session is defined by the duration of a database transaction.
If you use programmatic transaction demarcation in plain JSE without JTA, you are advised to
use the Hibernate <literal>Transaction</literal> API to hide the underlying transaction system
from your code. If you use JTA, use the JTA interfaces to demarcate transactions. If you
from your code. If you use JTA, you can utilize the JTA interfaces to demarcate transactions. If you
execute in an EJB container that supports CMT, transaction boundaries are defined declaratively
and you don't need any transaction or session demarcation operations in your code.
and you do not need any transaction or session demarcation operations in your code.
Refer to <xref linkend="transactions"/> for more information and code examples.
</para>
<para>
The <literal>hibernate.current_session_context_class</literal> configuration parameter
defines which <literal>org.hibernate.context.CurrentSessionContext</literal> implementation
should be used. Note that for backwards compatibility, if this config param is not set
should be used. For backwards compatibility, if this configuration parameter is not set
but a <literal>org.hibernate.transaction.TransactionManagerLookup</literal> is configured,
Hibernate will use the <literal>org.hibernate.context.JTASessionContext</literal>.
Typically, the value of this parameter would just name the implementation class to
use; for the three out-of-the-box implementations, however, there are three corresponding
short names, "jta", "thread", and "managed".
use. For the three out-of-the-box implementations, however, there are three corresponding
short names: "jta", "thread", and "managed".
</para>
</sect1>

View File

@ -33,22 +33,22 @@
<title>Introduction</title>
<para>
Association mappings are the often most difficult thing to get right. In
this section we'll go through the canonical cases one by one, starting
with unidirectional mappings, and then considering the bidirectional cases.
We'll use <literal>Person</literal> and <literal>Address</literal> in all
Association mappings are often the most difficult thing to implement correctly. In
this section we examine some canonical cases one by one, starting
with unidirectional mappings and then bidirectional cases.
We will use <literal>Person</literal> and <literal>Address</literal> in all
the examples.
</para>
<para>
We'll classify associations by whether or not they map to an intervening
join table, and by multiplicity.
Associations will be classified by multiplicity and whether or not they map to an intervening
join table.
</para>
<para>
Nullable foreign keys are not considered good practice in traditional data
modelling, so all our examples use not null foreign keys. This is not a
requirement of Hibernate, and the mappings will all work if you drop the
Nullable foreign keys are not considered to be good practice in traditional data
modelling, so our examples do not use nullable foreign keys. This is not a
requirement of Hibernate, and the mappings will work if you drop the
nullability constraints.
</para>
@ -58,7 +58,7 @@
<title>Unidirectional associations</title>
<sect2 id="assoc-unidirectional-m21">
<title>many to one</title>
<title>Many-to-one</title>
<para>
A <emphasis>unidirectional many-to-one association</emphasis> is the most
@ -87,7 +87,7 @@ create table Address ( addressId bigint not null primary key )
</sect2>
<sect2 id="assoc-unidirectional-121">
<title>one to one</title>
<title>One-to-one</title>
<para>
A <emphasis>unidirectional one-to-one association on a foreign key</emphasis>
@ -116,8 +116,8 @@ create table Address ( addressId bigint not null primary key )
<para>
A <emphasis>unidirectional one-to-one association on a primary key</emphasis>
usually uses a special id generator. (Notice that we've reversed the direction
of the association in this example.)
usually uses a special id generator In this example, however, we have reversed the direction
of the association:
</para>
<programlisting><![CDATA[<class name="Person">
@ -142,11 +142,11 @@ create table Address ( personId bigint not null primary key )
</sect2>
<sect2 id="assoc-unidirectional-12m">
<title>one to many</title>
<title>One-to-many</title>
<para>
A <emphasis>unidirectional one-to-many association on a foreign key</emphasis>
is a very unusual case, and is not really recommended.
is an unusual case, and is not recommended.
</para>
<programlisting><![CDATA[<class name="Person">
@ -171,7 +171,7 @@ create table Address ( addressId bigint not null primary key, personId bigint no
]]></programlisting>
<para>
We think it's better to use a join table for this kind of association.
You should instead use a join table for this kind of association.
</para>
</sect2>
@ -182,12 +182,12 @@ create table Address ( addressId bigint not null primary key, personId bigint no
<title>Unidirectional associations with join tables</title>
<sect2 id="assoc-unidirectional-join-12m">
<title>one to many</title>
<title>One-to-many</title>
<para>
A <emphasis>unidirectional one-to-many association on a join table</emphasis>
is much preferred. Notice that by specifying <literal>unique="true"</literal>,
we have changed the multiplicity from many-to-many to one-to-many.
is the preferred option. Specifying <literal>unique="true"</literal>,
changes the multiplicity from many-to-many to one-to-many.
</para>
<programlisting><![CDATA[<class name="Person">
@ -216,11 +216,11 @@ create table Address ( addressId bigint not null primary key )
</sect2>
<sect2 id="assoc-unidirectional-join-m21">
<title>many to one</title>
<title>Many-to-one</title>
<para>
A <emphasis>unidirectional many-to-one association on a join table</emphasis>
is quite common when the association is optional.
is common when the association is optional. For example:
</para>
<programlisting><![CDATA[<class name="Person">
@ -250,11 +250,11 @@ create table Address ( addressId bigint not null primary key )
</sect2>
<sect2 id="assoc-unidirectional-join-121">
<title>one to one</title>
<title>One-to-one</title>
<para>
A <emphasis>unidirectional one-to-one association on a join table</emphasis>
is extremely unusual, but possible.
A <emphasis>unidirectional one-to-one association on a join table</emphasis> is possible,
but extremely unusual.
</para>
<programlisting><![CDATA[<class name="Person">
@ -286,10 +286,10 @@ create table Address ( addressId bigint not null primary key )
</sect2>
<sect2 id="assoc-unidirectional-join-m2m">
<title>many to many</title>
<title>Many-to-many</title>
<para>
Finally, we have a <emphasis>unidirectional many-to-many association</emphasis>.
Finally, here is an example of a <emphasis>unidirectional many-to-many association</emphasis>.
</para>
<programlisting><![CDATA[<class name="Person">
@ -322,12 +322,12 @@ create table Address ( addressId bigint not null primary key )
<title>Bidirectional associations</title>
<sect2 id="assoc-bidirectional-m21" revision="2">
<title>one to many / many to one</title>
<title>one-to-many / many-to-one</title>
<para>
A <emphasis>bidirectional many-to-one association</emphasis> is the
most common kind of association. (This is the standard parent/child
relationship.)
most common kind of association. The following example illustrates the standard parent/child
relationship.
</para>
<programlisting><![CDATA[<class name="Person">
@ -355,11 +355,11 @@ create table Address ( addressId bigint not null primary key )
]]></programlisting>
<para>
If you use a <literal>List</literal> (or other indexed collection) you need
to set the <literal>key</literal> column of the foreign key to <literal>not null</literal>,
and let Hibernate manage the association from the collections side to maintain the index
of each element (making the other side virtually inverse by setting
<literal>update="false"</literal> and <literal>insert="false"</literal>):
If you use a <literal>List</literal>, or other indexed collection,
set the <literal>key</literal> column of the foreign key to <literal>not null</literal>.
Hibernate will manage the association from the collections side to maintain the index
of each element, making the other side virtually inverse by setting
<literal>update="false"</literal> and <literal>insert="false"</literal>:
</para>
<programlisting><![CDATA[<class name="Person">
@ -383,9 +383,10 @@ create table Address ( addressId bigint not null primary key )
</class>]]></programlisting>
<para>
It is important that you define <literal>not-null="true"</literal> on the
<literal>&lt;key&gt;</literal> element of the collection mapping if the
underlying foreign key column is <literal>NOT NULL</literal>. Don't only
If the underlying foreign key column is <literal>NOT NULL</literal>, it
is important that you define <literal>not-null="true"</literal> on the
<literal>&lt;key&gt;</literal> element of the collection mapping.
Do not only
declare <literal>not-null="true"</literal> on a possible nested
<literal>&lt;column&gt;</literal> element, but on the <literal>&lt;key&gt;</literal>
element.
@ -394,11 +395,11 @@ create table Address ( addressId bigint not null primary key )
</sect2>
<sect2 id="assoc-bidirectional-121">
<title>one to one</title>
<title>One-to-one</title>
<para>
A <emphasis>bidirectional one-to-one association on a foreign key</emphasis>
is quite common.
is common:
</para>
<programlisting><![CDATA[<class name="Person">
@ -425,7 +426,7 @@ create table Address ( addressId bigint not null primary key )
<para>
A <emphasis>bidirectional one-to-one association on a primary key</emphasis>
uses the special id generator.
uses the special id generator:
</para>
<programlisting><![CDATA[<class name="Person">
@ -457,11 +458,11 @@ create table Address ( personId bigint not null primary key )
<title>Bidirectional associations with join tables</title>
<sect2 id="assoc-bidirectional-join-12m">
<title>one to many / many to one</title>
<title>one-to-many / many-to-one</title>
<para>
A <emphasis>bidirectional one-to-many association on a join table</emphasis>.
Note that the <literal>inverse="true"</literal> can go on either end of the
The following is an example of a <emphasis>bidirectional one-to-many association on a join table</emphasis>.
The <literal>inverse="true"</literal> can go on either end of the
association, on the collection, or on the join.
</para>
@ -503,8 +504,8 @@ create table Address ( addressId bigint not null primary key )
<title>one to one</title>
<para>
A <emphasis>bidirectional one-to-one association on a join table</emphasis>
is extremely unusual, but possible.
A <emphasis>bidirectional one-to-one association on a join table</emphasis> is possible,
but extremely unusual.
</para>
<programlisting><![CDATA[<class name="Person">
@ -546,10 +547,10 @@ create table Address ( addressId bigint not null primary key )
</sect2>
<sect2 id="assoc-bidirectional-join-m2m" revision="1">
<title>many to many</title>
<title>Many-to-many</title>
<para>
Finally, we have a <emphasis>bidirectional many-to-many association</emphasis>.
Here is an example of a <emphasis>bidirectional many-to-many association</emphasis>.
</para>
<programlisting><![CDATA[<class name="Person">
@ -589,11 +590,11 @@ create table Address ( addressId bigint not null primary key )
<para>
More complex association joins are <emphasis>extremely</emphasis> rare.
Hibernate makes it possible to handle more complex situations using
Hibernate handles more complex situations by using
SQL fragments embedded in the mapping document. For example, if a table
with historical account information data defines
<literal>accountNumber</literal>, <literal>effectiveEndDate</literal>
and <literal>effectiveStartDate</literal>columns, mapped as follows:
and <literal>effectiveStartDate</literal>columns, it would be mapped as follows:
</para>
<programlisting><![CDATA[<properties name="currentAccountKey">
@ -606,8 +607,8 @@ create table Address ( addressId bigint not null primary key )
<property name="effectiveStateDate" type="date" not-null="true"/>]]></programlisting>
<para>
Then we can map an association to the <emphasis>current</emphasis> instance
(the one with null <literal>effectiveEndDate</literal>) using:
You can then map an association to the <emphasis>current</emphasis> instance,
the one with null <literal>effectiveEndDate</literal>, by using:
</para>
<programlisting><![CDATA[<many-to-one name="currentAccountInfo"
@ -621,8 +622,8 @@ create table Address ( addressId bigint not null primary key )
In a more complex example, imagine that the association between
<literal>Employee</literal> and <literal>Organization</literal> is maintained
in an <literal>Employment</literal> table full of historical employment data.
Then an association to the employee's <emphasis>most recent</emphasis> employer
(the one with the most recent <literal>startDate</literal>) might be mapped this way:
An association to the employee's <emphasis>most recent</emphasis> employer,
the one with the most recent <literal>startDate</literal>, could be mapped in the following way:
</para>
<programlisting><![CDATA[<join>
@ -639,7 +640,7 @@ create table Address ( addressId bigint not null primary key )
</join>]]></programlisting>
<para>
You can get quite creative with this functionality, but it is usually more practical
This functionality allows a degree of creativity and flexibility, but it is more practical
to handle these kinds of cases using HQL or a criteria query.
</para>

View File

@ -29,7 +29,7 @@
<title>Batch processing</title>
<para>
A naive approach to inserting 100 000 rows in the database using Hibernate might
A naive approach to inserting 100,000 rows in the database using Hibernate might
look like this:
</para>
@ -44,26 +44,27 @@ session.close();]]></programlisting>
<para>
This would fall over with an <literal>OutOfMemoryException</literal> somewhere
around the 50 000th row. That's because Hibernate caches all the newly inserted
<literal>Customer</literal> instances in the session-level cache.
around the 50,000th row. That is because Hibernate caches all the newly inserted
<literal>Customer</literal> instances in the session-level cache. In this chapter
we will show you how to avoid this problem.
</para>
<para>
In this chapter we'll show you how to avoid this problem. First, however, if you
are doing batch processing, it is absolutely critical that you enable the use of
JDBC batching, if you intend to achieve reasonable performance. Set the JDBC batch
size to a reasonable number (say, 10-50):
If you are undertaking batch processing you will need to enable the use of
JDBC batching. This is absolutely essential if you want to achieve optimal performance.
Set the JDBC batch size to a reasonable number (10-50, for example):
</para>
<programlisting><![CDATA[hibernate.jdbc.batch_size 20]]></programlisting>
<para id="disablebatching" revision="1">
Note that Hibernate disables insert batching at the JDBC level transparently if you
use an <literal>identiy</literal> identifier generator.
Hibernate disables insert batching at the JDBC level transparently if you
use an <literal>identity</literal> identifier generator.
</para>
<para>
You also might like to do this kind of work in a process where interaction with
You can also do this kind of work in a process where interaction with
the second-level cache is completely disabled:
</para>
@ -78,8 +79,8 @@ session.close();]]></programlisting>
<title>Batch inserts</title>
<para>
When making new objects persistent, you must <literal>flush()</literal> and
then <literal>clear()</literal> the session regularly, to control the size of
When making new objects persistent <literal>flush()</literal> and
then <literal>clear()</literal> the session regularly in order to control the size of
the first-level cache.
</para>
@ -105,7 +106,7 @@ session.close();]]></programlisting>
<title>Batch updates</title>
<para>
For retrieving and updating data the same ideas apply. In addition, you need to
For retrieving and updating data, the same ideas apply. In addition, you need to
use <literal>scroll()</literal> to take advantage of server-side cursors for
queries that return many rows of data.
</para>
@ -135,18 +136,18 @@ session.close();]]></programlisting>
<sect1 id="batch-statelesssession">
<title>The StatelessSession interface</title>
<para>
Alternatively, Hibernate provides a command-oriented API that may be used for
Alternatively, Hibernate provides a command-oriented API that can be used for
streaming data to and from the database in the form of detached objects. A
<literal>StatelessSession</literal> has no persistence context associated
with it and does not provide many of the higher-level life cycle semantics.
In particular, a stateless session does not implement a first-level cache nor
interact with any second-level or query cache. It does not implement
transactional write-behind or automatic dirty checking. Operations performed
using a stateless session do not ever cascade to associated instances. Collections
using a stateless session never cascade to associated instances. Collections
are ignored by a stateless session. Operations performed via a stateless session
bypass Hibernate's event model and interceptors. Stateless sessions are vulnerable
to data aliasing effects, due to the lack of a first-level cache. A stateless
session is a lower-level abstraction, much closer to the underlying JDBC.
bypass Hibernate's event model and interceptors. Due to the lack of a first-level cache,
Stateless sessions are vulnerable to data aliasing effects. A stateless
session is a lower-level abstraction that is much closer to the underlying JDBC.
</para>
<programlisting><![CDATA[StatelessSession session = sessionFactory.openStatelessSession();
@ -164,7 +165,7 @@ tx.commit();
session.close();]]></programlisting>
<para>
Note that in this code example, the <literal>Customer</literal> instances returned
In this code example, the <literal>Customer</literal> instances returned
by the query are immediately detached. They are never associated with any persistence
context.
</para>
@ -172,9 +173,9 @@ session.close();]]></programlisting>
<para>
The <literal>insert(), update()</literal> and <literal>delete()</literal> operations
defined by the <literal>StatelessSession</literal> interface are considered to be
direct database row-level operations, which result in immediate execution of a SQL
<literal>INSERT, UPDATE</literal> or <literal>DELETE</literal> respectively. Thus,
they have very different semantics to the <literal>save(), saveOrUpdate()</literal>
direct database row-level operations. They result in the immediate execution of a SQL
<literal>INSERT, UPDATE</literal> or <literal>DELETE</literal> respectively.
They have different semantics to the <literal>save(), saveOrUpdate()</literal>
and <literal>delete()</literal> operations defined by the <literal>Session</literal>
interface.
</para>
@ -186,18 +187,20 @@ session.close();]]></programlisting>
<para>
As already discussed, automatic and transparent object/relational mapping is concerned
with the management of object state. This implies that the object state is available
in memory, hence manipulating (using the SQL <literal>Data Manipulation Language</literal>
(DML) statements: <literal>INSERT</literal>, <literal>UPDATE</literal>, <literal>DELETE</literal>)
data directly in the database will not affect in-memory state. However, Hibernate provides methods
for bulk SQL-style DML statement execution which are performed through the
with the management of the object state. The object state is available in memory. This means that manipulating data directly in the database (using the SQL <literal>Data Manipulation Language</literal>
(DML) the statements: <literal>INSERT</literal>, <literal>UPDATE</literal>, <literal>DELETE</literal>)
will not affect in-memory state. However, Hibernate provides methods
for bulk SQL-style DML statement execution that is performed through the
Hibernate Query Language (<link linkend="queryhql">HQL</link>).
</para>
<para>
The pseudo-syntax for <literal>UPDATE</literal> and <literal>DELETE</literal> statements
is: <literal>( UPDATE | DELETE ) FROM? EntityName (WHERE where_conditions)?</literal>. Some
points to note:
is: <literal>( UPDATE | DELETE ) FROM? EntityName (WHERE where_conditions)?</literal>.
</para>
<para>
Some points to note:
</para>
<itemizedlist spacing="compact">
@ -208,17 +211,17 @@ session.close();]]></programlisting>
</listitem>
<listitem>
<para>
There can only be a single entity named in the from-clause; it can optionally be
There can only be a single entity named in the from-clause. It can, however, be
aliased. If the entity name is aliased, then any property references must
be qualified using that alias; if the entity name is not aliased, then it is
be qualified using that alias. If the entity name is not aliased, then it is
illegal for any property references to be qualified.
</para>
</listitem>
<listitem>
<para>
No <link linkend="queryhql-joins-forms">joins</link> (either implicit or explicit)
can be specified in a bulk HQL query. Sub-queries may be used in the where-clause;
the subqueries, themselves, may contain joins.
No <link linkend="queryhql-joins-forms">joins</link>, either implicit or explicit,
can be specified in a bulk HQL query. Sub-queries can be used in the where-clause, where
the subqueries themselves may contain joins.
</para>
</listitem>
<listitem>
@ -230,8 +233,8 @@ session.close();]]></programlisting>
<para>
As an example, to execute an HQL <literal>UPDATE</literal>, use the
<literal>Query.executeUpdate()</literal> method (the method is named for
those familiar with JDBC's <literal>PreparedStatement.executeUpdate()</literal>):
<literal>Query.executeUpdate()</literal> method. The method is named for
those familiar with JDBC's <literal>PreparedStatement.executeUpdate()</literal>:
</para>
<programlisting><![CDATA[Session session = sessionFactory.openSession();
@ -247,11 +250,11 @@ tx.commit();
session.close();]]></programlisting>
<para>
HQL <literal>UPDATE</literal> statements, by default do not effect the
In keeping with the EJB3 specification, HQL <literal>UPDATE</literal> statements, by default, do not effect the
<link linkend="mapping-declaration-version">version</link>
or the <link linkend="mapping-declaration-timestamp">timestamp</link> property values
for the affected entities; this is in keeping with the EJB3 specification. However,
you can force Hibernate to properly reset the <literal>version</literal> or
for the affected entities. However,
you can force Hibernate to reset the <literal>version</literal> or
<literal>timestamp</literal> property values through the use of a <literal>versioned update</literal>.
This is achieved by adding the <literal>VERSIONED</literal> keyword after the <literal>UPDATE</literal>
keyword.
@ -267,7 +270,7 @@ tx.commit();
session.close();]]></programlisting>
<para>
Note that custom version types (<literal>org.hibernate.usertype.UserVersionType</literal>)
Custom version types, <literal>org.hibernate.usertype.UserVersionType</literal>,
are not allowed in conjunction with a <literal>update versioned</literal> statement.
</para>
@ -289,13 +292,13 @@ session.close();]]></programlisting>
<para>
The <literal>int</literal> value returned by the <literal>Query.executeUpdate()</literal>
method indicate the number of entities effected by the operation. Consider this may or may not
method indicates the number of entities effected by the operation. This may or may not
correlate to the number of rows effected in the database. An HQL bulk operation might result in
multiple actual SQL statements being executed, for joined-subclass, for example. The returned
multiple actual SQL statements being executed (for joined-subclass, for example). The returned
number indicates the number of actual entities affected by the statement. Going back to the
example of joined-subclass, a delete against one of the subclasses may actually result
in deletes against not just the table to which that subclass is mapped, but also the "root"
table and potentially joined-subclass tables further down the inheritence hierarchy.
table and potentially joined-subclass tables further down the inheritance hierarchy.
</para>
<para>
@ -310,10 +313,10 @@ session.close();]]></programlisting>
Only the INSERT INTO ... SELECT ... form is supported; not the INSERT INTO ... VALUES ... form.
</para>
<para>
The properties_list is analogous to the <literal>column speficiation</literal>
The properties_list is analogous to the <literal>column specification</literal>
in the SQL <literal>INSERT</literal> statement. For entities involved in mapped
inheritence, only properties directly defined on that given class-level can be
used in the properties_list. Superclass properties are not allowed; and subclass
inheritance, only properties directly defined on that given class-level can be
used in the properties_list. Superclass properties are not allowed and subclass
properties do not make sense. In other words, <literal>INSERT</literal>
statements are inherently non-polymorphic.
</para>
@ -322,8 +325,8 @@ session.close();]]></programlisting>
<para>
select_statement can be any valid HQL select query, with the caveat that the return types
must match the types expected by the insert. Currently, this is checked during query
compilation rather than allowing the check to relegate to the database. Note however
that this might cause problems between Hibernate <literal>Type</literal>s which are
compilation rather than allowing the check to relegate to the database.
This might, however, cause problems between Hibernate <literal>Type</literal>s which are
<emphasis>equivalent</emphasis> as opposed to <emphasis>equal</emphasis>. This might cause
issues with mismatches between a property defined as a <literal>org.hibernate.type.DateType</literal>
and a property defined as a <literal>org.hibernate.type.TimestampType</literal>, even though the
@ -333,14 +336,14 @@ session.close();]]></programlisting>
<listitem>
<para>
For the id property, the insert statement gives you two options. You can either
explicitly specify the id property in the properties_list (in which case its value
is taken from the corresponding select expression) or omit it from the properties_list
(in which case a generated value is used). This later option is only available when
explicitly specify the id property in the properties_list, in which case its value
is taken from the corresponding select expression, or omit it from the properties_list,
in which case a generated value is used. This latter option is only available when
using id generators that operate in the database; attempting to use this option with
any "in memory" type generators will cause an exception during parsing. Note that
for the purposes of this discussion, in-database generators are considered to be
any "in memory" type generators will cause an exception during parsing.
For the purposes of this discussion, in-database generators are considered to be
<literal>org.hibernate.id.SequenceGenerator</literal> (and its subclasses) and
any implementors of <literal>org.hibernate.id.PostInsertIdentifierGenerator</literal>.
any implementers of <literal>org.hibernate.id.PostInsertIdentifierGenerator</literal>.
The most notable exception here is <literal>org.hibernate.id.TableHiLoGenerator</literal>,
which cannot be used because it does not expose a selectable way to get its values.
</para>
@ -349,15 +352,15 @@ session.close();]]></programlisting>
<para>
For properties mapped as either <literal>version</literal> or <literal>timestamp</literal>,
the insert statement gives you two options. You can either specify the property in the
properties_list (in which case its value is taken from the corresponding select expressions)
or omit it from the properties_list (in which case the <literal>seed value</literal> defined
by the <literal>org.hibernate.type.VersionType</literal> is used).
properties_list, in which case its value is taken from the corresponding select expressions,
or omit it from the properties_list, in which case the <literal>seed value</literal> defined
by the <literal>org.hibernate.type.VersionType</literal> is used.
</para>
</listitem>
</itemizedlist>
<para>
An example HQL <literal>INSERT</literal> statement execution:
The following is an example of an HQL <literal>INSERT</literal> statement execution:
</para>
<programlisting><![CDATA[Session session = sessionFactory.openSession();

View File

@ -30,7 +30,7 @@
<variablelist spacing="compact">
<varlistentry>
<term>Write fine-grained classes and map them using <literal>&lt;component&gt;</literal>.</term>
<term>Write fine-grained classes and map them using <literal>&lt;component&gt;</literal>:</term>
<listitem>
<para>
Use an <literal>Address</literal> class to encapsulate <literal>street</literal>,
@ -40,17 +40,17 @@
</listitem>
</varlistentry>
<varlistentry>
<term>Declare identifier properties on persistent classes.</term>
<term>Declare identifier properties on persistent classes:</term>
<listitem>
<para>
Hibernate makes identifier properties optional. There are all sorts of reasons why
you should use them. We recommend that identifiers be 'synthetic' (generated, with
no business meaning).
Hibernate makes identifier properties optional. There are a range of reasons why
you should use them. We recommend that identifiers be 'synthetic', that is, generated with
no business meaning.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Identify natural keys.</term>
<term>Identify natural keys:</term>
<listitem>
<para>
Identify natural keys for all entities, and map them using
@ -60,17 +60,17 @@
</listitem>
</varlistentry>
<varlistentry>
<term>Place each class mapping in its own file.</term>
<term>Place each class mapping in its own file:</term>
<listitem>
<para>
Don't use a single monolithic mapping document. Map <literal>com.eg.Foo</literal> in
the file <literal>com/eg/Foo.hbm.xml</literal>. This makes particularly good sense in
Do not use a single monolithic mapping document. Map <literal>com.eg.Foo</literal> in
the file <literal>com/eg/Foo.hbm.xml</literal>. This makes sense, particularly in
a team environment.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Load mappings as resources.</term>
<term>Load mappings as resources:</term>
<listitem>
<para>
Deploy the mappings along with the classes they map.
@ -78,11 +78,11 @@
</listitem>
</varlistentry>
<varlistentry>
<term>Consider externalising query strings.</term>
<term>Consider externalizing query strings:</term>
<listitem>
<para>
This is a good practice if your queries call non-ANSI-standard SQL functions.
Externalising the query strings to mapping files will make the application more
This is recommended if your queries call non-ANSI-standard SQL functions.
Externalizing the query strings to mapping files will make the application more
portable.
</para>
</listitem>
@ -91,103 +91,103 @@
<term>Use bind variables.</term>
<listitem>
<para>
As in JDBC, always replace non-constant values by "?". Never use string manipulation to
bind a non-constant value in a query! Even better, consider using named parameters in
As in JDBC, always replace non-constant values by "?". Do not use string manipulation to
bind a non-constant value in a query. You should also consider using named parameters in
queries.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Don't manage your own JDBC connections.</term>
<term>Do not manage your own JDBC connections:</term>
<listitem>
<para>
Hibernate lets the application manage JDBC connections. This approach should be considered
a last-resort. If you can't use the built-in connections providers, consider providing your
Hibernate allows the application to manage JDBC connections, but his approach should be considered
a last-resort. If you cannot use the built-in connection providers, consider providing your
own implementation of <literal>org.hibernate.connection.ConnectionProvider</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Consider using a custom type.</term>
<term>Consider using a custom type:</term>
<listitem>
<para>
Suppose you have a Java type, say from some library, that needs to be persisted but doesn't
Suppose you have a Java type from a library that needs to be persisted but does not
provide the accessors needed to map it as a component. You should consider implementing
<literal>org.hibernate.UserType</literal>. This approach frees the application
code from implementing transformations to / from a Hibernate type.
code from implementing transformations to/from a Hibernate type.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Use hand-coded JDBC in bottlenecks.</term>
<term>Use hand-coded JDBC in bottlenecks:</term>
<listitem>
<para>
In performance-critical areas of the system, some kinds of operations might benefit from
direct JDBC. But please, wait until you <emphasis>know</emphasis> something is a bottleneck.
And don't assume that direct JDBC is necessarily faster. If you need to use direct JDBC, it might
be worth opening a Hibernate <literal>Session</literal> and using that JDBC connection. That
direct JDBC. Do not assume, however, that JDBC is necessarily faster. Please wait until you <emphasis>know</emphasis> something is a bottleneck.
If you need to use direct JDBC,
you can open a Hibernate <literal>Session</literal> and usingfile:///usr/share/doc/HTML/en-US/index.html that JDBC connection. This
way you can still use the same transaction strategy and underlying connection provider.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Understand <literal>Session</literal> flushing.</term>
<term>Understand <literal>Session</literal> flushing:</term>
<listitem>
<para>
From time to time the Session synchronizes its persistent state with the database. Performance will
be affected if this process occurs too often. You may sometimes minimize unnecessary flushing by
disabling automatic flushing or even by changing the order of queries and other operations within a
Sometimes the Session synchronizes its persistent state with the database. Performance will
be affected if this process occurs too often. You can sometimes minimize unnecessary flushing by
disabling automatic flushing, or even by changing the order of queries and other operations within a
particular transaction.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>In a three tiered architecture, consider using detached objects.</term>
<term>In a three tiered architecture, consider using detached objects:</term>
<listitem>
<para>
When using a servlet / session bean architecture, you could pass persistent objects loaded in
the session bean to and from the servlet / JSP layer. Use a new session to service each request.
When using a servlet/session bean architecture, you can pass persistent objects loaded in
the session bean to and from the servlet/JSP layer. Use a new session to service each request.
Use <literal>Session.merge()</literal> or <literal>Session.saveOrUpdate()</literal> to
synchronize objects with the database.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>In a two tiered architecture, consider using long persistence contexts.</term>
<term>In a two tiered architecture, consider using long persistence contexts:</term>
<listitem>
<para>
Database Transactions have to be as short as possible for best scalability. However, it is often
neccessary to implement long running <emphasis>application transactions</emphasis>, a single
necessary to implement long running <emphasis>application transactions</emphasis>, a single
unit-of-work from the point of view of a user. An application transaction might span several
client request/response cycles. It is common to use detached objects to implement application
transactions. An alternative, extremely appropriate in two tiered architecture, is to maintain
a single open persistence contact (session) for the whole life cycle of the application transaction
and simply disconnect from the JDBC connection at the end of each request and reconnect at the
transactions. An appropriate alternative in a two tiered architecture, is to maintain
a single open persistence contact session for the whole life cycle of the application transaction. Then
simply disconnect from the JDBC connection at the end of each request and reconnect at the
beginning of the subsequent request. Never share a single session across more than one application
transaction, or you will be working with stale data.
transaction or you will be working with stale data.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Don't treat exceptions as recoverable.</term>
<term>Do not treat exceptions as recoverable:</term>
<listitem>
<para>
This is more of a necessary practice than a "best" practice. When an exception occurs, roll back
the <literal>Transaction</literal> and close the <literal>Session</literal>. If you don't, Hibernate
can't guarantee that in-memory state accurately represents persistent state. As a special case of this,
the <literal>Transaction</literal> and close the <literal>Session</literal>. If you do not do this, Hibernate
cannot guarantee that in-memory state accurately represents the persistent state. For example,
do not use <literal>Session.load()</literal> to determine if an instance with the given identifier
exists on the database; use <literal>Session.get()</literal> or a query instead.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Prefer lazy fetching for associations.</term>
<term>Prefer lazy fetching for associations:</term>
<listitem>
<para>
Use eager fetching sparingly. Use proxies and lazy collections for most associations to classes that
are not likely to be completely held in the second-level cache. For associations to cached classes,
where there is an a extremely high probability of a cache hit, explicitly disable eager fetching using
<literal>lazy="false"</literal>. When an join fetching is appropriate to a particular use
<literal>lazy="false"</literal>. When join fetching is appropriate to a particular use
case, use a query with a <literal>left join fetch</literal>.
</para>
</listitem>
@ -195,7 +195,7 @@
<varlistentry>
<term>
Use the <emphasis>open session in view</emphasis> pattern, or a disciplined
<emphasis>assembly phase</emphasis> to avoid problems with unfetched data.
<emphasis>assembly phase</emphasis> to avoid problems with unfetched data:
</term>
<listitem>
<para>
@ -203,40 +203,40 @@
In a traditional EJB architecture, DTOs serve dual purposes: first, they work around the problem
that entity beans are not serializable; second, they implicitly define an assembly phase where
all data to be used by the view is fetched and marshalled into the DTOs before returning control
to the presentation tier. Hibernate eliminates the first purpose. However, you will still need
an assembly phase (think of your business methods as having a strict contract with the presentation
tier about what data is available in the detached objects) unless you are prepared to hold the
persistence context (the session) open across the view rendering process. This is not a limitation
of Hibernate! It is a fundamental requirement of safe transactional data access.
to the presentation tier. Hibernate eliminates the first purpose. Unless you are prepared to hold the
persistence context (the session) open across the view rendering process, you will still need
an assembly phase. Think of your business methods as having a strict contract with the presentation
tier about what data is available in the detached objects. This is not a limitation
of Hibernate. It is a fundamental requirement of safe transactional data access.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Consider abstracting your business logic from Hibernate.</term>
<term>Consider abstracting your business logic from Hibernate:</term>
<listitem>
<para>
Hide (Hibernate) data-access code behind an interface. Combine the <emphasis>DAO</emphasis> and
Hide Hibernate data-access code behind an interface. Combine the <emphasis>DAO</emphasis> and
<emphasis>Thread Local Session</emphasis> patterns. You can even have some classes persisted by
handcoded JDBC, associated to Hibernate via a <literal>UserType</literal>. (This advice is
intended for "sufficiently large" applications; it is not appropriate for an application with
five tables!)
handcoded JDBC associated to Hibernate via a <literal>UserType</literal>. This advice is, however,
intended for "sufficiently large" applications. It is not appropriate for an application with
five tables.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Don't use exotic association mappings.</term>
<term>Do not use exotic association mappings:</term>
<listitem>
<para>
Good usecases for a real many-to-many associations are rare. Most of the time you need
Practical test cases for real many-to-many associations are rare. Most of the time you need
additional information stored in the "link table". In this case, it is much better to
use two one-to-many associations to an intermediate link class. In fact, we think that
most associations are one-to-many and many-to-one, you should be careful when using any
other association style and ask yourself if it is really neccessary.
use two one-to-many associations to an intermediate link class. In fact,
most associations are one-to-many and many-to-one. For this reason, you should proceed cautiously when using any
other association style.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Prefer bidirectional associations.</term>
<term>Prefer bidirectional associations:</term>
<listitem>
<para>
Unidirectional associations are more difficult to query. In a large application, almost

View File

@ -26,14 +26,14 @@
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="collections">
<title>Collection Mapping</title>
<title>Collection mapping</title>
<sect1 id="collections-persistent" revision="3">
<title>Persistent collections</title>
<para>
Hibernate requires that persistent collection-valued fields be declared
as an interface type, for example:
as an interface type. For example:
</para>
<programlisting><![CDATA[public class Product {
@ -50,19 +50,19 @@
The actual interface might be <literal>java.util.Set</literal>,
<literal>java.util.Collection</literal>, <literal>java.util.List</literal>,
<literal>java.util.Map</literal>, <literal>java.util.SortedSet</literal>,
<literal>java.util.SortedMap</literal> or ... anything you like! (Where
"anything you like" means you will have to write an implementation of
<literal>java.util.SortedMap</literal> or anything you like
("anything you like" means you will have to write an implementation of
<literal>org.hibernate.usertype.UserCollectionType</literal>.)
</para>
<para>
Notice how we initialized the instance variable with an instance of
Notice how the instance variable was initialized with an instance of
<literal>HashSet</literal>. This is the best way to initialize collection
valued properties of newly instantiated (non-persistent) instances. When
you make the instance persistent - by calling <literal>persist()</literal>,
for example - Hibernate will actually replace the <literal>HashSet</literal>
you make the instance persistent, by calling <literal>persist()</literal>
for example, Hibernate will actually replace the <literal>HashSet</literal>
with an instance of Hibernate's own implementation of <literal>Set</literal>.
Watch out for errors like this:
Be aware of the following errors:
</para>
<programlisting><![CDATA[Cat cat = new DomesticCat();
@ -79,24 +79,24 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
The persistent collections injected by Hibernate behave like
<literal>HashMap</literal>, <literal>HashSet</literal>,
<literal>TreeMap</literal>, <literal>TreeSet</literal> or
<literal>ArrayList</literal>, depending upon the interface type.
<literal>ArrayList</literal>, depending on the interface type.
</para>
<para>
Collections instances have the usual behavior of value types. They are
automatically persisted when referenced by a persistent object and
automatically deleted when unreferenced. If a collection is passed from one
are automatically deleted when unreferenced. If a collection is passed from one
persistent object to another, its elements might be moved from one table to
another. Two entities may not share a reference to the same collection
another. Two entities cannot share a reference to the same collection
instance. Due to the underlying relational model, collection-valued properties
do not support null value semantics; Hibernate does not distinguish between
do not support null value semantics. Hibernate does not distinguish between
a null collection reference and an empty collection.
</para>
<para>
You shouldn't have to worry much about any of this. Use persistent collections
the same way you use ordinary Java collections. Just make sure you understand
the semantics of bidirectional associations (discussed later).
Use persistent collections
the same way you use ordinary Java collections. However, please ensure you understand
the semantics of bidirectional associations (these are discussed later).
</para>
</sect1>
@ -106,15 +106,15 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<tip>
<para>
There are quite a range of mappings that can be generated for collections, covering
There are quite a range of mappings that can be generated for collections that cover
many common relational models. We suggest you experiment with the schema generation tool
to get a feeling for how various mapping declarations translate to database tables.
so that you understand how various mapping declarations translate to database tables.
</para>
</tip>
<para>
The Hibernate mapping element used for mapping a collection depends upon
the type of the interface. For example, a <literal>&lt;set&gt;</literal>
the type of interface. For example, a <literal>&lt;set&gt;</literal>
element is used for mapping properties of type <literal>Set</literal>.
</para>
@ -177,94 +177,94 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<calloutlist>
<callout arearefs="mappingcollection1">
<para>
<literal>name</literal> the collection property name
<literal>name</literal>: the collection property name
</para>
</callout>
<callout arearefs="mappingcollection2">
<para>
<literal>table</literal> (optional - defaults to property name) the
name of the collection table (not used for one-to-many associations)
<literal>table</literal> (optional - defaults to property name): the
name of the collection table. It is not used for one-to-many associations.
</para>
</callout>
<callout arearefs="mappingcollection3">
<para>
<literal>schema</literal> (optional) the name of a table schema to
<literal>schema</literal> (optional): the name of a table schema to
override the schema declared on the root element
</para>
</callout>
<callout arearefs="mappingcollection4">
<para>
<literal>lazy</literal> (optional - defaults to <literal>true</literal>)
may be used to disable lazy fetching and specify that the association is
always eagerly fetched, or to enable "extra-lazy" fetching where most
operations do not initialize the collection (suitable for very large
collections)
<literal>lazy</literal> (optional - defaults to <literal>true</literal>):
disables lazy fetching and specifies that the association is
always eagerly fetched. It can also be used to enable "extra-lazy" fetching where most
operations do not initialize the collection. This is suitable for large
collections.
</para>
</callout>
<callout arearefs="mappingcollection5">
<para>
<literal>inverse</literal> (optional - defaults to <literal>false</literal>)
mark this collection as the "inverse" end of a bidirectional association
<literal>inverse</literal> (optional - defaults to <literal>false</literal>):
marks this collection as the "inverse" end of a bidirectional association.
</para>
</callout>
<callout arearefs="mappingcollection6">
<para>
<literal>cascade</literal> (optional - defaults to <literal>none</literal>)
enable operations to cascade to child entities
<literal>cascade</literal> (optional - defaults to <literal>none</literal>):
enables operations to cascade to child entities.
</para>
</callout>
<callout arearefs="mappingcollection7">
<para>
<literal>sort</literal> (optional) specify a sorted collection with
<literal>natural</literal> sort order, or a given comparator class
<literal>sort</literal> (optional): specifies a sorted collection with
<literal>natural</literal> sort order or a given comparator class.
</para>
</callout>
<callout arearefs="mappingcollection8">
<para>
<literal>order-by</literal> (optional, JDK1.4 only) specify a table column (or columns)
<literal>order-by</literal> (optional, JDK1.4 only): specifies a table column or columns
that define the iteration order of the <literal>Map</literal>, <literal>Set</literal>
or bag, together with an optional <literal>asc</literal> or <literal>desc</literal>
or bag, together with an optional <literal>asc</literal> or <literal>desc</literal>.
</para>
</callout>
<callout arearefs="mappingcollection9">
<para>
<literal>where</literal> (optional) specify an arbitrary SQL <literal>WHERE</literal>
condition to be used when retrieving or removing the collection (useful if the
collection should contain only a subset of the available data)
<literal>where</literal> (optional): specifies an arbitrary SQL <literal>WHERE</literal>
condition that is used when retrieving or removing the collection. This is useful if the
collection needs to contain only a subset of the available data.
</para>
</callout>
<callout arearefs="mappingcollection10">
<para>
<literal>fetch</literal> (optional, defaults to <literal>select</literal>) Choose
<literal>fetch</literal> (optional, defaults to <literal>select</literal>): chooses
between outer-join fetching, fetching by sequential select, and fetching by sequential
subselect.
</para>
</callout>
<callout arearefs="mappingcollection11">
<para>
<literal>batch-size</literal> (optional, defaults to <literal>1</literal>) specify a
<literal>batch-size</literal> (optional, defaults to <literal>1</literal>): specifies a
"batch size" for lazily fetching instances of this collection.
</para>
</callout>
<callout arearefs="mappingcollection12">
<para>
<literal>access</literal> (optional - defaults to <literal>property</literal>): The
strategy Hibernate should use for accessing the collection property value.
<literal>access</literal> (optional - defaults to <literal>property</literal>): the
strategy Hibernate uses for accessing the collection property value.
</para>
</callout>
<callout arearefs="mappingcollection13">
<para>
<literal>optimistic-lock</literal> (optional - defaults to <literal>true</literal>):
Species that changes to the state of the collection results in increment of the
owning entity's version. (For one to many associations, it is often reasonable to
disable this setting.)
specifies that changes to the state of the collection results in increments of the
owning entity's version. For one-to-many associations you may want to
disable this setting.
</para>
</callout>
<callout arearefs="mappingcollection14">
<para>
<literal>mutable</literal> (optional - defaults to <literal>true</literal>):
A value of <literal>false</literal> specifies that the elements of the
collection never change (a minor performance optimization in some cases).
a value of <literal>false</literal> specifies that the elements of the
collection never change. This allows for minor performance optimization in some cases.
</para>
</callout>
</calloutlist>
@ -276,22 +276,22 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<para>
Collection instances are distinguished in the database by the foreign key of
the entity that owns the collection. This foreign key is referred to as the
<emphasis>collection key column</emphasis> (or columns) of the collection
<emphasis>collection key column</emphasis>, or columns, of the collection
table. The collection key column is mapped by the <literal>&lt;key&gt;</literal>
element.
</para>
<para>
There may be a nullability constraint on the foreign key column. For most
collections, this is implied. For unidirectional one to many associations,
the foreign key column is nullable by default, so you might need to specify
There can be a nullability constraint on the foreign key column. For most
collections, this is implied. For unidirectional one-to-many associations,
the foreign key column is nullable by default, so you may need to specify
<literal>not-null="true"</literal>.
</para>
<programlisting><![CDATA[<key column="productSerialNumber" not-null="true"/>]]></programlisting>
<para>
The foreign key constraint may use <literal>ON DELETE CASCADE</literal>.
The foreign key constraint can use <literal>ON DELETE CASCADE</literal>.
</para>
<programlisting><![CDATA[<key column="productSerialNumber" on-delete="cascade"/>]]></programlisting>
@ -307,12 +307,12 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<title>Collection elements</title>
<para>
Collections may contain almost any other Hibernate type, including all basic types,
custom types, components, and of course, references to other entities. This is an
important distinction: an object in a collection might be handled with "value"
semantics (its life cycle fully depends on the collection owner) or it might be a
reference to another entity, with its own life cycle. In the latter case, only the
"link" between the two objects is considered to be state held by the collection.
Collections can contain almost any other Hibernate type, including: basic types,
custom types, components and references to other entities. This is an
important distinction. An object in a collection might be handled with "value"
semantics (its life cycle fully depends on the collection owner), or it might be a
reference to another entity with its own life cycle. In the latter case, only the
"link" between the two objects is considered to be a state held by the collection.
</para>
<para>
@ -331,15 +331,15 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<para>
All collection mappings, except those with set and bag semantics, need an
<emphasis>index column</emphasis> in the collection table - a column that maps to an
<emphasis>index column</emphasis> in the collection table. An index column is 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, mapped with
<literal>&lt;map-key&gt;</literal>, it may be an entity reference mapped with
<literal>&lt;map-key-many-to-many&gt;</literal>, or it may be a composite type,
<literal>&lt;map-key&gt;</literal>. It can be an entity reference mapped with
<literal>&lt;map-key-many-to-many&gt;</literal>, or it can be a composite type
mapped with <literal>&lt;composite-map-key&gt;</literal>. The index of an array or
list is always of type <literal>integer</literal> and is mapped using the
<literal>&lt;list-index&gt;</literal> element. The mapped column contains
sequential integers (numbered from zero, by default).
sequential integers that are numbered from zero by default.
</para>
<programlistingco>
@ -353,13 +353,13 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<calloutlist>
<callout arearefs="index1">
<para>
<literal>column_name</literal> (required): The name of the column holding the
<literal>column_name</literal> (required): the name of the column holding the
collection index values.
</para>
</callout>
<callout arearefs="index1">
<para>
<literal>base</literal> (optional, defaults to <literal>0</literal>): The value
<literal>base</literal> (optional - defaults to <literal>0</literal>): the value
of the index column that corresponds to the first element of the list or array.
</para>
</callout>
@ -381,19 +381,19 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<calloutlist>
<callout arearefs="mapkey1">
<para>
<literal>column</literal> (optional): The name of the column holding the
<literal>column</literal> (optional): the name of the column holding the
collection index values.
</para>
</callout>
<callout arearefs="mapkey2">
<para>
<literal>formula</literal> (optional): A SQL formula used to evaluate the
<literal>formula</literal> (optional): a SQL formula used to evaluate the
key of the map.
</para>
</callout>
<callout arearefs="mapkey3">
<para>
<literal>type</literal> (reguired): The type of the map keys.
<literal>type</literal> (required): the type of the map keys.
</para>
</callout>
</calloutlist>
@ -413,19 +413,19 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<calloutlist>
<callout arearefs="indexmanytomany1">
<para>
<literal>column</literal> (optional): The name of the foreign key
<literal>column</literal> (optional): the name of the foreign key
column for the collection index values.
</para>
</callout>
<callout arearefs="indexmanytomany2">
<para>
<literal>formula</literal> (optional): A SQL formula used to evaluate the
<literal>formula</literal> (optional): a SQ formula used to evaluate the
foreign key of the map key.
</para>
</callout>
<callout arearefs="indexmanytomany3">
<para>
<literal>class</literal> (required): The entity class used as the map key.
<literal>class</literal> (required): the entity class used as the map key.
</para>
</callout>
</calloutlist>
@ -433,9 +433,9 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<para>
If your table doesn't have an index column, and you still wish to use <literal>List</literal>
as the property type, you should map the property as a Hibernate <emphasis>&lt;bag&gt;</emphasis>.
A bag does not retain its order when it is retrieved from the database, but it may be
If your table does not have an index column, and you still wish to use <literal>List</literal>
as the property type, you can map the property as a Hibernate <emphasis>&lt;bag&gt;</emphasis>.
A bag does not retain its order when it is retrieved from the database, but it can be
optionally sorted or ordered.
</para>
@ -445,14 +445,14 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<title>Collections of values and many-to-many associations</title>
<para>
Any collection of values or many-to-many association requires a dedicated
Any collection of values or many-to-many associations requires a dedicated
<emphasis>collection table</emphasis> with a foreign key column or columns,
<emphasis>collection element column</emphasis> or columns and possibly
<emphasis>collection element column</emphasis> or columns, and possibly
an index column or columns.
</para>
<para>
For a collection of values, we use the <literal>&lt;element&gt;</literal> tag.
For a collection of values use the <literal>&lt;element&gt;</literal> tag. For example:
</para>
<programlistingco>
@ -475,19 +475,19 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<calloutlist>
<callout arearefs="element1b">
<para>
<literal>column</literal> (optional): The name of the column holding the
<literal>column</literal> (optional): the name of the column holding the
collection element values.
</para>
</callout>
<callout arearefs="element2b">
<para>
<literal>formula</literal> (optional): An SQL formula used to evaluate the
<literal>formula</literal> (optional): an SQL formula used to evaluate the
element.
</para>
</callout>
<callout arearefs="element3b">
<para>
<literal>type</literal> (required): The type of the collection element.
<literal>type</literal> (required): the type of the collection element.
</para>
</callout>
</calloutlist>
@ -524,54 +524,54 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<calloutlist>
<callout arearefs="manytomany1">
<para>
<literal>column</literal> (optional): The name of the element foreign key column.
<literal>column</literal> (optional): the name of the element foreign key column.
</para>
</callout>
<callout arearefs="manytomany2">
<para>
<literal>formula</literal> (optional): An SQL formula used to evaluate the element
<literal>formula</literal> (optional): an SQL formula used to evaluate the element
foreign key value.
</para>
</callout>
<callout arearefs="manytomany3">
<para>
<literal>class</literal> (required): The name of the associated class.
<literal>class</literal> (required): the name of the associated class.
</para>
</callout>
<callout arearefs="manytomany4">
<para>
<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>)
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,
enable <literal>join</literal> fetching,not only of the collection itself,
but also with this attribute on the <literal>&lt;many-to-many&gt;</literal>
nested element.
</para>
</callout>
<callout arearefs="manytomany5">
<para>
<literal>unique</literal> (optional): Enable the DDL generation of a unique
<literal>unique</literal> (optional): enables the DDL generation of a unique
constraint for the foreign-key column. This makes the association multiplicity
effectively one to many.
effectively one-to-many.
</para>
</callout>
<callout arearefs="manytomany6">
<para>
<literal>not-found</literal> (optional - defaults to <literal>exception</literal>):
Specifies how foreign keys that reference missing rows will be handled:
specifies how foreign keys that reference missing rows will be handled:
<literal>ignore</literal> will treat a missing row as a null association.
</para>
</callout>
<callout arearefs="manytomany7">
<para>
<literal>entity-name</literal> (optional): The entity name of the associated class,
<literal>entity-name</literal> (optional): the entity name of the associated class,
as an alternative to <literal>class</literal>.
</para>
</callout>
<callout arearefs="manytomany8">
<para>
<literal>property-ref</literal>: (optional) The name of a property of the associated
<literal>property-ref</literal> (optional): the name of a property of the associated
class that is joined to this foreign key. If not specified, the primary key of
the associated class is used.
</para>
@ -579,8 +579,11 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
</calloutlist>
</programlistingco>
<para>
Here are some examples.
</para>
<para>
Some examples, first, a set of strings:
A set of strings:
</para>
<programlisting><![CDATA[<set name="names" table="person_names">
@ -589,8 +592,8 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
</set>]]></programlisting>
<para>
A bag containing integers (with an iteration order determined by the
<literal>order-by</literal> attribute):
A bag containing integers with an iteration order determined by the
<literal>order-by</literal> attribute:
</para>
<programlisting><![CDATA[<bag name="sizes"
@ -601,7 +604,7 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
</bag>]]></programlisting>
<para>
An array of entities - in this case, a many to many association:
An array of entities, in this case, a many-to-many association:
</para>
<programlisting><![CDATA[<array name="addresses"
@ -626,7 +629,7 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
</map>]]></programlisting>
<para>
A list of components (discussed in the next chapter):
A list of components (this is discussed in the next chapter):
</para>
<programlisting><![CDATA[<list name="carComponents"
@ -646,30 +649,30 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<title>One-to-many associations</title>
<para>
A <emphasis>one to many association</emphasis> links the tables of two classes
via a foreign key, with no intervening collection table. This mapping loses
A <emphasis>one-to-many association</emphasis> links the tables of two classes
via a foreign key with no intervening collection table. This mapping loses
certain semantics of normal Java collections:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
An instance of the contained entity class may not belong to more than
one instance of the collection
An instance of the contained entity class cannot belong to more than
one instance of the collection.
</para>
</listitem>
<listitem>
<para>
An instance of the contained entity class may not appear at more than
one value of the collection index
An instance of the contained entity class cannot appear at more than
one value of the collection index.
</para>
</listitem>
</itemizedlist>
<para>
An association from <literal>Product</literal> to <literal>Part</literal> requires
existence of a foreign key column and possibly an index column to the <literal>Part</literal>
table. A <literal>&lt;one-to-many&gt;</literal> tag indicates that this is a one to many
the existence of a foreign key column and possibly an index column to the <literal>Part</literal>
table. A <literal>&lt;one-to-many&gt;</literal> tag indicates that this is a one-to-many
association.
</para>
@ -689,19 +692,19 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<calloutlist>
<callout arearefs="onetomany1">
<para>
<literal>class</literal> (required): The name of the associated class.
<literal>class</literal> (required): the name of the associated class.
</para>
</callout>
<callout arearefs="onetomany2">
<para>
<literal>not-found</literal> (optional - defaults to <literal>exception</literal>):
Specifies how cached identifiers that reference missing rows will be handled:
specifies how cached identifiers that reference missing rows will be handled.
<literal>ignore</literal> will treat a missing row as a null association.
</para>
</callout>
<callout arearefs="onetomany3">
<para>
<literal>entity-name</literal> (optional): The entity name of the associated class,
<literal>entity-name</literal> (optional): the entity name of the associated class,
as an alternative to <literal>class</literal>.
</para>
</callout>
@ -709,24 +712,26 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
</programlistingco>
<para>
Notice that the <literal>&lt;one-to-many&gt;</literal> element does not need to
The <literal>&lt;one-to-many&gt;</literal> element does not need to
declare any columns. Nor is it necessary to specify the <literal>table</literal>
name anywhere.
</para>
<para>
<emphasis>Very important note:</emphasis> If the foreign key column of a
<warning>
<para>
If the foreign key column of a
<literal>&lt;one-to-many&gt;</literal> association is declared <literal>NOT NULL</literal>,
you must declare the <literal>&lt;key&gt;</literal> mapping
<literal>not-null="true"</literal> or <emphasis>use a bidirectional association</emphasis>
with the collection mapping marked <literal>inverse="true"</literal>. See the discussion
of bidirectional associations later in this chapter.
of bidirectional associations later in this chapter for more information.
</para>
</warning>
<para>
This example shows a map of <literal>Part</literal> entities by name (where
<literal>partName</literal> is a persistent property of <literal>Part</literal>).
Notice the use of a formula-based index.
The following example shows a map of <literal>Part</literal> entities by name, where
<literal>partName</literal> is a persistent property of <literal>Part</literal>.
Notice the use of a formula-based index:
</para>
<programlisting><![CDATA[<map name="parts"
@ -775,12 +780,12 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
</para>
<para>
If you want the database itself to order the collection elements use the
If you want the database itself to order the collection elements, use the
<literal>order-by</literal> attribute of <literal>set</literal>, <literal>bag</literal>
or <literal>map</literal> mappings. This solution is only available under
JDK 1.4 or higher (it is implemented using <literal>LinkedHashSet</literal> or
<literal>LinkedHashMap</literal>). This performs the ordering in the SQL query,
not in memory.
JDK 1.4 or higher and is implemented using <literal>LinkedHashSet</literal> or
<literal>LinkedHashMap</literal>. This performs the ordering in the SQL query and
not in the memory.
</para>
<programlisting><![CDATA[<set name="aliases" table="person_aliases" order-by="lower(name) asc">
@ -794,14 +799,17 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<element column="hol_date type="date"/>
</map>]]></programlisting>
<para>
Note that the value of the <literal>order-by</literal> attribute is an SQL ordering, not
a HQL ordering!
<note>
<title>Note</title>
<para>
The value of the <literal>order-by</literal> attribute is an SQL ordering, not
an HQL ordering.
</para>
</note>
<para>
Associations may even be sorted by some arbitrary criteria at runtime using a collection
<literal>filter()</literal>.
Associations can even be sorted by arbitrary criteria at runtime using a collection
<literal>filter()</literal>:
</para>
<programlisting><![CDATA[sortedUsers = s.createFilter( group.getUsers(), "order by this.name" ).list();]]></programlisting>
@ -821,7 +829,7 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<term>one-to-many</term>
<listitem>
<para>
set or bag valued at one end, single-valued at the other
set or bag valued at one end and single-valued at the other
</para>
</listitem>
</varlistentry>
@ -838,14 +846,14 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
</para>
<para>
You may specify a bidirectional many-to-many association simply by mapping two
You can specify a bidirectional many-to-many association 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, but it can not be an
indexed collection).
<emphasis>inverse</emphasis>. You cannot select an
indexed collection.
</para>
<para>
Here's an example of a bidirectional many-to-many association; each category can
Here is an example of a bidirectional many-to-many association that illustrates how each category can
have many items and each item can be in many categories:
</para>
@ -872,9 +880,9 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
<para>
Changes made only to the inverse end of the association are <emphasis>not</emphasis>
persisted. This means that Hibernate has two representations in memory for every
bidirectional association, one link from A to B and another link from B to A. This
is easier to understand if you think about the Java object model and how we create
a many-to-many relationship in Java:
bidirectional association: one link from A to B and another link from B to A. This
is easier to understand if you think about the Java object model and how
a many-to-many relationship in Javais created:
</para>
<programlisting><![CDATA[
@ -889,7 +897,7 @@ session.persist(category); // The relationship will be saved]]></p
</para>
<para>
You may define a bidirectional one-to-many association by mapping a one-to-many association
You can define 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>
@ -913,8 +921,8 @@ session.persist(category); // The relationship will be saved]]></p
</class>]]></programlisting>
<para>
Mapping one end of an association with <literal>inverse="true"</literal> doesn't
affect the operation of cascades, these are orthogonal concepts!
Mapping one end of an association with <literal>inverse="true"</literal> does not
affect the operation of cascades as these are orthogonal concepts.
</para>
</sect2>
@ -923,8 +931,8 @@ session.persist(category); // The relationship will be saved]]></p
<title>Bidirectional associations with indexed collections</title>
<para>
A bidirectional association where one end is represented as a <literal>&lt;list&gt;</literal>
or <literal>&lt;map&gt;</literal> requires special consideration. If there is a property of
the child class which maps to the index column, no problem, we can continue using
or <literal>&lt;map&gt;</literal>, requires special consideration. If there is a property of
the child class that maps to the index column you can use
<literal>inverse="true"</literal> on the collection mapping:
</para>
@ -951,10 +959,10 @@ session.persist(category); // The relationship will be saved]]></p
</class>]]></programlisting>
<para>
But, if there is no such property on the child class, we can't think of the association as
truly bidirectional (there is information available at one end of the association that is
not available at the other end). In this case, we can't map the collection
<literal>inverse="true"</literal>. Instead, we could use the following mapping:
If there is no such property on the child class, the association cannot be considered
truly bidirectional. That is, there is information available at one end of the association that is
not available at the other end. In this case, you cannot map the collection
<literal>inverse="true"</literal>. Instead, you could use the following mapping:
</para>
<programlisting><![CDATA[<class name="Parent">
@ -982,7 +990,7 @@ session.persist(category); // The relationship will be saved]]></p
<para>
Note that in this mapping, the collection-valued end of the association is responsible for
updates to the foreign key. TODO: Does this really result in some unnecessary update statements?
updates to the foreign key. <!--TODO: Does this really result in some unnecessary update statements?-->
</para>
</sect2>
@ -991,7 +999,7 @@ session.persist(category); // The relationship will be saved]]></p
<title>Ternary associations</title>
<para>
There are three possible approaches to mapping a ternary association. One is to use a
There are three possible approaches to mapping a ternary association. One approach is to use a
<literal>Map</literal> with an association as its index:
</para>
@ -1008,12 +1016,12 @@ session.persist(category); // The relationship will be saved]]></p
</map>]]></programlisting>
<para>
A second approach is to simply remodel the association as an entity class. This
is the approach we use most commonly.
A second approach is to remodel the association as an entity class. This
is the most common approach.
</para>
<para>
A final alternative is to use composite elements, which we will discuss later.
A final alternative is to use composite elements, which will be discussed later.
</para>
</sect2>
@ -1022,19 +1030,18 @@ session.persist(category); // The relationship will be saved]]></p
<title><literal>Using an &lt;idbag&gt;</literal></title>
<para>
If you've fully embraced our view that composite keys are a bad thing and that
entities should have synthetic identifiers (surrogate keys), then you might
find it a bit odd that the many to many associations and collections of values
that we've shown so far all map to tables with composite keys! Now, this point
is quite arguable; a pure association table doesn't seem to benefit much from
a surrogate key (though a collection of composite values <emphasis>might</emphasis>).
Nevertheless, Hibernate provides a feature that allows you to map many to many
The majority of the many-to-many associations and collections of values
shown previously all map to tables with composite keys, even though it has been have suggested
that entities should have synthetic identifiers (surrogate keys). A
pure association table does not seem to benefit much from
a surrogate key, although a collection of composite values <emphasis>might</emphasis>.
It is for this reason that Hibernate provides a feature that allows you to map many-to-many
associations and collections of values to a table with a surrogate key.
</para>
<para>
The <literal>&lt;idbag&gt;</literal> element lets you map a <literal>List</literal>
(or <literal>Collection</literal>) with bag semantics.
(or <literal>Collection</literal>) with bag semantics. For example:
</para>
<programlisting><![CDATA[<idbag name="lovers" table="LOVERS">
@ -1046,17 +1053,16 @@ session.persist(category); // The relationship will be saved]]></p
</idbag>]]></programlisting>
<para>
As you can see, an <literal>&lt;idbag&gt;</literal> has a synthetic id generator,
just like an entity class! A different surrogate key is assigned to each collection
row. Hibernate does not provide any mechanism to discover the surrogate key value
of a particular row, however.
An <literal>&lt;idbag&gt;</literal> has a synthetic id generator,
just like an entity class. A different surrogate key is assigned to each collection
row. Hibernate does not, however, provide any mechanism for discovering the surrogate key value
of a particular row.
</para>
<para>
Note that the update performance of an <literal>&lt;idbag&gt;</literal> is
<emphasis>much</emphasis> better than a regular <literal>&lt;bag&gt;</literal>!
The update performance of an <literal>&lt;idbag&gt;</literal> supersedes a regular <literal>&lt;bag&gt;</literal>.
Hibernate can locate individual rows efficiently and update or delete them
individually, just like a list, map or set.
individually, similar to a list, map or set.
</para>
<para>
@ -1086,8 +1092,11 @@ session.persist(category); // The relationship will be saved]]></p
<title>Collection examples</title>
<para>
The previous sections are pretty confusing. So lets look at an example. This
class:
This section covers collection examples.
</para>
<para>
The following class has a collection of <literal>Child</literal> instances:
</para>
<programlisting><![CDATA[package eg;
@ -1108,9 +1117,9 @@ public class Parent {
}]]></programlisting>
<para>
has a collection of <literal>Child</literal> instances. If each
child has at most one parent, the most natural mapping is a
If each child has, at most, one parent, the most natural mapping is a
one-to-many association:
</para>
<programlisting><![CDATA[<hibernate-mapping>
@ -1181,7 +1190,7 @@ create table child ( id bigint not null
alter table child add constraint childfk0 (parent_id) references parent]]></programlisting>
<para>
Alternatively, if you absolutely insist that this association should be unidirectional,
Alternatively, if this association must be unidirectional
you can declare the <literal>NOT NULL</literal> constraint on the <literal>&lt;key&gt;</literal>
mapping:
</para>
@ -1208,7 +1217,7 @@ alter table child add constraint childfk0 (parent_id) references parent]]></prog
</hibernate-mapping>]]></programlisting>
<para>
On the other hand, if a child might have multiple parents, a many-to-many
On the other hand, if a child has multiple parents, a many-to-many
association is appropriate:
</para>
@ -1246,12 +1255,12 @@ alter table childset add constraint childsetfk0 (parent_id) references parent
alter table childset add constraint childsetfk1 (child_id) references child]]></programlisting>
<para>
For more examples and a complete walk-through a parent/child relationship mapping,
see <xref linkend="example-parentchild"/>.
For more examples and a complete explanation of a parent/child relationship mapping,
see <xref linkend="example-parentchild"/> for more information.
</para>
<para>
Even more exotic association mappings are possible, we will catalog all possibilities
Even more complex association mappings are covered
in the next chapter.
</para>

View File

@ -29,17 +29,17 @@
<title>Component Mapping</title>
<para>
The notion of a <emphasis>component</emphasis> is re-used in several different contexts,
for different purposes, throughout Hibernate.
The notion of a <emphasis>component</emphasis> is re-used in several different contexts and purposes
throughout Hibernate.
</para>
<sect1 id="components-dependentobjects" revision="2" >
<title>Dependent objects</title>
<para>
A component is a contained object that is persisted as a value type, not an entity
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
(not to architecture-level components). For example, you might model a person like this:
and not to architecture-level components. For example, you can model a person like this:
</para>
<programlisting><![CDATA[public class Person {
@ -93,14 +93,14 @@
}]]></programlisting>
<para>
Now <literal>Name</literal> may be persisted as a component of
<literal>Person</literal>. Notice that <literal>Name</literal> defines getter
and setter methods for its persistent properties, but doesn't need to declare
Now <literal>Name</literal> can be persisted as a component of
<literal>Person</literal>. <literal>Name</literal> 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:
Our Hibernate mapping would look like this:
</para>
<programlisting><![CDATA[<class name="eg.Person" table="person">
@ -124,18 +124,17 @@
</para>
<para>
Like all value types, components do not support shared references. In other words, two
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 ojects, only "the same" by value. The null value semantics of a component are
name objects that were 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.
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 may be of any Hibernate type (collections, many-to-one
The properties of a component can be of any Hibernate type (collections, many-to-one
associations, other components, etc). Nested components should <emphasis>not</emphasis>
be considered an exotic usage. Hibernate is intended to support a very fine-grained
be considered an exotic usage. Hibernate is intended to support a fine-grained
object model.
</para>
@ -164,10 +163,10 @@
<title>Collections of dependent objects</title>
<para>
Collections of components are supported (eg. an array of type
Collections of components are supported (e.g. an array of type
<literal>Name</literal>). Declare your component collection by
replacing the <literal>&lt;element&gt;</literal> tag with a
<literal>&lt;composite-element&gt;</literal> tag.
<literal>&lt;composite-element&gt;</literal> tag:
</para>
<programlisting><![CDATA[<set name="someNames" table="some_names" lazy="true">
@ -179,29 +178,31 @@
</composite-element>
</set>]]></programlisting>
<para>
Note: if you define a <literal>Set</literal> of composite elements, it is
very important to implement <literal>equals()</literal> and
<important>
<para>
If you define a <literal>Set</literal> of composite elements, it is
important to implement <literal>equals()</literal> and
<literal>hashCode()</literal> correctly.
</para>
</important>
</para>
<para>
Composite elements may contain components but not collections. If your
composite element itself contains
Composite elements can contain components but not collections. If your
composite element contains
components, use the <literal>&lt;nested-composite-element&gt;</literal>
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
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>
Please note that a composite element mapping doesn't support null-able properties
if you're using a <literal>&lt;set&gt;</literal>. 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),
A composite element mapping does not support null-able properties
if you are using a <literal>&lt;set&gt;</literal>. 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>&lt;list&gt;</literal>, <literal>&lt;map&gt;</literal>,
@ -210,10 +211,10 @@
<para>
A special case of a composite element is a composite element with a nested
<literal>&lt;many-to-one&gt;</literal> element. A mapping like this allows
<literal>&lt;many-to-one&gt;</literal> 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</literal> to <literal>Item</literal> where
from <literal>Order</literal> to <literal>Item</literal>, where
<literal>purchaseDate</literal>, <literal>price</literal> and
<literal>quantity</literal> are properties of the association:
</para>
@ -232,10 +233,10 @@
</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>
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</literal> can be in the
set of an <literal>Order</literal>, but it cannot be referenced by the <literal>Item</literal>
at the same time.
</para>
@ -253,7 +254,7 @@
</class>]]></programlisting>
<para>
Composite elements may appear in queries using the same syntax as
Composite elements can appear in queries using the same syntax as
associations to other entities.
</para>
@ -263,8 +264,8 @@
<title>Components as Map indices</title>
<para>
The <literal>&lt;composite-map-key&gt;</literal> element lets you map a
component class as the key of a <literal>Map</literal>. Make sure you override
The <literal>&lt;composite-map-key&gt;</literal> element allows you to map a
component class as the key of a <literal>Map</literal>. Ensure that you override
<literal>hashCode()</literal> and <literal>equals()</literal> correctly on
the component class.
</para>
@ -274,7 +275,7 @@
<title>Components as composite identifiers</title>
<para>
You may use a component as an identifier of an entity class. Your component
You can use a component as an identifier of an entity class. Your component
class must satisfy certain requirements:
</para>
@ -287,25 +288,28 @@
<listitem>
<para>
It must re-implement <literal>equals()</literal> and
<literal>hashCode()</literal>, consistently with the database's
<literal>hashCode()</literal> consistently with the database's
notion of composite key equality.
</para>
</listitem>
</itemizedlist>
<note>
<title>Note</title>
<para>
<emphasis>Note: in Hibernate3, the second requirement is not an absolutely hard
requirement of Hibernate. But do it anyway.</emphasis>
In Hibernate3, although the second requirement is not an absolutely hard
requirement of Hibernate, it is recommended.
</para>
<para>
You can't use an <literal>IdentifierGenerator</literal> to generate composite keys.
</note>
<para>
You cannot use an <literal>IdentifierGenerator</literal> to generate composite keys.
Instead the application must assign its own identifiers.
</para>
<para>
Use the <literal>&lt;composite-id&gt;</literal> tag (with nested
<literal>&lt;key-property&gt;</literal> elements) in place of the usual
Use the <literal>&lt;composite-id&gt;</literal> tag, with nested
<literal>&lt;key-property&gt;</literal> elements, in place of the usual
<literal>&lt;id&gt;</literal> declaration. For example, the
<literal>OrderLine</literal> class has a primary key that depends upon
the (composite) primary key of <literal>Order</literal>.
@ -331,9 +335,9 @@
</class>]]></programlisting>
<para>
Now, any foreign keys referencing the <literal>OrderLine</literal> table are also
composite. You must declare this in your mappings for other classes. An association
to <literal>OrderLine</literal> would be mapped like this:
Any foreign keys referencing the <literal>OrderLine</literal> table are now
composite. Declare this in your mappings for other classes. An association
to <literal>OrderLine</literal> is mapped like this:
</para>
<programlisting><![CDATA[<many-to-one name="orderLine" class="OrderLine">
@ -343,12 +347,17 @@
<column name="customerId"/>
</many-to-one>]]></programlisting>
<para>
(Note that the <literal>&lt;column&gt;</literal> tag is an alternative to the
<literal>column</literal> attribute everywhere.)
<note>
</title>
Note
</title>
<para>
The <literal>&lt;column&gt;</literal> tag is an alternative to the
<literal>column</literal> attribute everywhere.
</para>
</note>
<para>
<para>
A <literal>many-to-many</literal> association to <literal>OrderLine</literal> also
uses the composite foreign key:
</para>
@ -376,7 +385,7 @@
</set>]]></programlisting>
<para>
(The <literal>&lt;one-to-many&gt;</literal> element, as usual, declares no columns.)
The <literal>&lt;one-to-many&gt;</literal> element declares no columns.
</para>
<para>
@ -406,7 +415,7 @@
<title>Dynamic components</title>
<para>
You may even map a property of type <literal>Map</literal>:
You can also map a property of type <literal>Map</literal>:
</para>
<programlisting><![CDATA[<dynamic-component name="userAttributes">
@ -418,9 +427,9 @@
<para>
The semantics of a <literal>&lt;dynamic-component&gt;</literal> mapping are identical
to <literal>&lt;component&gt;</literal>. The advantage of this kind of mapping is
the ability to determine the actual properties of the bean at deployment time, just
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. Even better, you can access (and change) Hibernate's
also possible, using a DOM parser. You can also access, and change, Hibernate's
configuration-time metamodel via the <literal>Configuration</literal> object.
</para>

View File

@ -29,11 +29,11 @@
<title>Configuration</title>
<para>
Because Hibernate is designed to operate in many different environments, there
are a large number of configuration parameters. Fortunately, most have sensible
Hibernate is designed to operate in many different environments and, as such, there
is a broad range of configuration parameters. Fortunately, most have sensible
default values and Hibernate is distributed with an example
<literal>hibernate.properties</literal> file in <literal>etc/</literal> that shows
the various options. Just put the example file in your classpath and customize it.
<literal>hibernate.properties</literal> file in <literal>etc/</literal> that displays
the various options. Simply put the example file in your classpath and customize it to suit your needs.
</para>
<sect1 id="configuration-programmatic" revision="1">
@ -42,14 +42,14 @@
<para>
An instance of <classname>org.hibernate.cfg.Configuration</classname> represents an entire set of mappings
of an application's Java types to an SQL database. The <classname>org.hibernate.cfg.Configuration</classname>
is used to build an (immutable) <interfacename>org.hibernate.SessionFactory</interfacename>. The mappings
is used to build an immutable <interfacename>org.hibernate.SessionFactory</interfacename>. The mappings
are compiled from various XML mapping files.
</para>
<para>
You may obtain a <classname>org.hibernate.cfg.Configuration</classname> instance by instantiating
You can obtain a <classname>org.hibernate.cfg.Configuration</classname> instance by instantiating
it directly and specifying XML mapping documents. If the mapping files are in the classpath,
use <literal>addResource()</literal>:
use <literal>addResource()</literal>. For example:
</para>
<programlisting><![CDATA[Configuration cfg = new Configuration()
@ -57,8 +57,8 @@
.addResource("Bid.hbm.xml");]]></programlisting>
<para>
An alternative (sometimes better) way is to specify the mapped class, and
let Hibernate find the mapping document for you:
An alternative way is to specify the mapped class and
allow Hibernate to find the mapping document for you:
</para>
<programlisting><![CDATA[Configuration cfg = new Configuration()
@ -66,14 +66,14 @@
.addClass(org.hibernate.auction.Bid.class);]]></programlisting>
<para>
Then Hibernate will look for mapping files named <filename>/org/hibernate/auction/Item.hbm.xml</filename>
Hibernate will then search for mapping files named <filename>/org/hibernate/auction/Item.hbm.xml</filename>
and <filename>/org/hibernate/auction/Bid.hbm.xml</filename> in the classpath. This approach eliminates any
hardcoded filenames.
</para>
<para>
A <classname>org.hibernate.cfg.Configuration</classname> also allows you to specify configuration
properties:
properties. For example:
</para>
<programlisting><![CDATA[Configuration cfg = new Configuration()
@ -85,7 +85,7 @@
<para>
This is not the only way to pass configuration properties to Hibernate.
The various options include:
Some alternative options include:
</para>
<orderedlist spacing="compact">
@ -108,18 +108,18 @@
<listitem>
<para>
Include <literal>&lt;property&gt;</literal> elements in
<literal>hibernate.cfg.xml</literal> (discussed later).
<literal>hibernate.cfg.xml</literal> (this is discussed later).
</para>
</listitem>
</orderedlist>
<para>
<filename>hibernate.properties</filename> is the easiest approach if you want to get started quickly.
If you want to get started quickly<filename>hibernate.properties</filename> is the easiest approach.
</para>
<para>
The <classname>org.hibernate.cfg.Configuration</classname> is intended as a startup-time object,
to be discarded once a <literal>SessionFactory</literal> is created.
The <classname>org.hibernate.cfg.Configuration</classname> is intended as a startup-time object that will
be discarded once a <literal>SessionFactory</literal> is created.
</para>
</sect1>
@ -147,7 +147,7 @@
<title>JDBC connections</title>
<para>
Usually, you want to have the <interfacename>org.hibernate.SessionFactory</interfacename> create and pool
It is advisable to have the <interfacename>org.hibernate.SessionFactory</interfacename> create and pool
JDBC connections for you. If you take this approach, opening a <interfacename>org.hibernate.Session</interfacename>
is as simple as:
</para>
@ -155,18 +155,18 @@
<programlisting><![CDATA[Session session = sessions.openSession(); // open a new Session]]></programlisting>
<para>
As soon as you do something that requires access to the database, a JDBC connection will be obtained from
Once you start a task that requires access to the database, a JDBC connection will be obtained from
the pool.
</para>
<para>
For this to work, we need to pass some JDBC connection properties to Hibernate. All Hibernate property
names and semantics are defined on the class <classname>org.hibernate.cfg.Environment</classname>. We will
now describe the most important settings for JDBC connection configuration.
Before you can do this, you first need to pass some JDBC connection properties to Hibernate. All Hibernate property
names and semantics are defined on the class <classname>org.hibernate.cfg.Environment</classname>.
The most important settings for JDBC connection configuration are outlined below.
</para>
<para>
Hibernate will obtain (and pool) connections using <classname>java.sql.DriverManager</classname>
Hibernate will obtain and pool connections using <classname>java.sql.DriverManager</classname>
if you set the following properties:
</para>
@ -227,25 +227,25 @@
</table>
<para>
Hibernate's own connection pooling algorithm is however quite rudimentary.
Hibernate's own connection pooling algorithm is, however, quite rudimentary.
It is intended to help you get started and is <emphasis>not intended for use
in a production system</emphasis> or even for performance testing. You should
in a production system</emphasis>, or even for performance testing. You should
use a third party pool for best performance and stability. Just replace the
<property>hibernate.connection.pool_size</property> property with connection
pool specific settings. This will turn off Hibernate's internal pool. For
example, you might like to use C3P0.
example, you might like to use c3p0.
</para>
<para>
C3P0 is an open source JDBC connection pool distributed along with Hibernate in the <filename>lib</filename>
directory. Hibernate will use its <classname>org.hibernate.connection.C3P0ConnectionProvider</classname>
for connection pooling if you set <property>hibernate.c3p0.*</property> properties. If you'd like to use Proxool
for connection pooling if you set <property>hibernate.c3p0.*</property> properties. If you would like to use Proxool,
refer to the packaged <filename>hibernate.properties</filename> and the Hibernate web site for more
information.
</para>
<para>
Here is an example <filename>hibernate.properties</filename> file for C3P0:
The following is an example <filename>hibernate.properties</filename> file for c3p0:
</para>
<programlisting id="c3p0-configuration" revision="1"><![CDATA[hibernate.connection.driver_class = org.postgresql.Driver
@ -260,7 +260,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para>
For use inside an application server, you should almost always configure Hibernate to obtain connections
from an application server <interfacename>javax.sql.Datasource</interfacename> registered in JNDI. You'll
from an application server <interfacename>javax.sql.Datasource</interfacename> registered in JNDI. You will
need to set at least one of the following properties:
</para>
@ -321,7 +321,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</table>
<para>
Here's an example <filename>hibernate.properties</filename> file for an application server provided JNDI
Here is an example <filename>hibernate.properties</filename> file for an application server provided JNDI
datasource:
</para>
@ -338,13 +338,13 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</para>
<para>
Arbitrary connection properties may be given by prepending "<literal>hibernate.connection</literal>" to the
connection property name. For example, you may specify a <property>charSet</property>
Arbitrary connection properties can be given by prepending "<literal>hibernate.connection</literal>" to the
connection property name. For example, you can specify a <property>charSet</property>
connection property using <property>hibernate.connection.charSet</property>.
</para>
<para>
You may define your own plugin strategy for obtaining JDBC connections by implementing the
You can define your own plugin strategy for obtaining JDBC connections by implementing the
interface <interfacename>org.hibernate.connection.ConnectionProvider</interfacename>, and specifying your
custom implementation via the <property>hibernate.connection.provider_class</property> property.
</para>
@ -355,14 +355,14 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<title>Optional configuration properties</title>
<para>
There are a number of other properties that control the behaviour of Hibernate at runtime. All are optional
There are a number of other properties that control the behavior of Hibernate at runtime. All are optional
and have reasonable default values.
</para>
<para>
<emphasis>Warning: some of these properties are "system-level" only.</emphasis> System-level properties can
<warning><emphasis>Some of these properties are "system-level" only.</emphasis> System-level properties can
be set only via <literal>java -Dproperty=value</literal> or <filename>hibernate.properties</filename>. They
may <emphasis>not</emphasis> be set by the other techniques described above.
<emphasis>cannot</emphasis> be set by the other techniques described above.</warning>
</para>
<table frame="topbot" id="configuration-optional-properties" revision="8">
@ -385,12 +385,12 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
The classname of a Hibernate <classname>org.hibernate.dialect.Dialect</classname> which
allows Hibernate to generate SQL optimized for a particular relational database.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>full.classname.of.Dialect</literal>
</para>
<para>
In most cases Hibernate will actually be able to chose the correct
<classname>org.hibernate.dialect.Dialect</classname> implementation to use based on the
In most cases Hibernate will actually be able to choose the correct
<classname>org.hibernate.dialect.Dialect</classname> implementation based on the
<literal>JDBC metadata</literal> returned by the JDBC driver.
</para>
</entry>
@ -404,7 +404,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
to setting the log category <literal>org.hibernate.SQL</literal>
to <literal>debug</literal>.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
@ -416,7 +416,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<entry>
Pretty print the SQL in the log and console.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
@ -429,7 +429,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
Qualify unqualified table names with the given schema/tablespace
in generated SQL.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>SCHEMA_NAME</literal>
</para>
</entry>
@ -439,10 +439,10 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<property>hibernate.default_catalog</property>
</entry>
<entry>
Qualify unqualified table names with the given catalog
Qualifies unqualified table names with the given catalog
in generated SQL.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>CATALOG_NAME</literal>
</para>
</entry>
@ -455,7 +455,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
The <interfacename>org.hibernate.SessionFactory</interfacename> will be automatically
bound to this name in JNDI after it has been created.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>jndi/composite/name</literal>
</para>
</entry>
@ -465,11 +465,11 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<property>hibernate.max_fetch_depth</property>
</entry>
<entry>
Set a maximum "depth" for the outer join fetch tree
Sets a maximum "depth" for the outer join fetch tree
for single-ended associations (one-to-one, many-to-one).
A <literal>0</literal> disables default outer join fetching.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
recommended values between <literal>0</literal> and
<literal>3</literal>
</para>
@ -480,9 +480,9 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<property>hibernate.default_batch_fetch_size</property>
</entry>
<entry>
Set a default size for Hibernate batch fetching of associations.
Sets a default size for Hibernate batch fetching of associations.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
recommended values <literal>4</literal>, <literal>8</literal>,
<literal>16</literal>
</para>
@ -493,7 +493,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<property>hibernate.default_entity_mode</property>
</entry>
<entry>
Set a default mode for entity representation for all sessions
Sets a default mode for entity representation for all sessions
opened from this <literal>SessionFactory</literal>
<para>
<literal>dynamic-map</literal>, <literal>dom4j</literal>,
@ -506,11 +506,11 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<property>hibernate.order_updates</property>
</entry>
<entry>
Force Hibernate to order SQL updates by the primary key value
Forces Hibernate to order SQL updates by the primary key value
of the items being updated. This will result in fewer transaction
deadlocks in highly concurrent systems.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
@ -523,7 +523,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
If enabled, Hibernate will collect statistics useful for
performance tuning.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
@ -536,7 +536,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
If enabled, generated identifier properties will be
reset to default values when objects are deleted.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
@ -549,7 +549,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
If turned on, Hibernate will generate comments inside the SQL, for
easier debugging, defaults to <literal>false</literal>.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
@ -588,7 +588,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<entry>
A non-zero value enables use of JDBC2 batch updates by Hibernate.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
recommended values between <literal>5</literal> and <literal>30</literal>
</para>
</entry>
@ -599,11 +599,11 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</entry>
<entry>
Set this property to <literal>true</literal> if your JDBC driver returns
correct row counts from <literal>executeBatch()</literal> (it is usually
safe to turn this option on). Hibernate will then use batched DML for
correct row counts from <literal>executeBatch()</literal>. Iit is usually
safe to turn this option on. Hibernate will then use batched DML for
automatically versioned data. Defaults to <literal>false</literal>.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
@ -616,7 +616,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
Select a custom <interfacename>org.hibernate.jdbc.Batcher</interfacename>. Most applications
will not need this configuration property.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>classname.of.BatcherFactory</literal>
</para>
</entry>
@ -627,10 +627,10 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</entry>
<entry>
Enables use of JDBC2 scrollable resultsets by Hibernate.
This property is only necessary when using user supplied
JDBC connections, Hibernate uses connection metadata otherwise.
This property is only necessary when using user-supplied
JDBC connections. Hibernate uses connection metadata otherwise.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
@ -643,7 +643,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
Use streams when writing/reading <literal>binary</literal> or <literal>serializable</literal>
types to/from JDBC. <emphasis>*system-level property*</emphasis>
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
@ -653,13 +653,13 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<property>hibernate.jdbc.use_get_generated_keys</property>
</entry>
<entry>
Enable use of JDBC3 <literal>PreparedStatement.getGeneratedKeys()</literal>
Enables use of JDBC3 <literal>PreparedStatement.getGeneratedKeys()</literal>
to retrieve natively generated keys after insert. Requires JDBC3+ driver
and JRE1.4+, set to false if your driver has problems with the Hibernate
identifier generators. By default, tries to determine the driver capabilities
identifier generators. By default, it tries to determine the driver capabilities
using connection metadata.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true|false</literal>
</para>
</entry>
@ -672,7 +672,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
The classname of a custom <interfacename>org.hibernate.connection.ConnectionProvider</interfacename>
which provides JDBC connections to Hibernate.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>classname.of.ConnectionProvider</literal>
</para>
</entry>
@ -682,11 +682,11 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<property>hibernate.connection.isolation</property>
</entry>
<entry>
Set the JDBC transaction isolation level. Check <interfacename>java.sql.Connection</interfacename>
for meaningful values but note that most databases do not support all isolation levels and some
Sets the JDBC transaction isolation level. Check <interfacename>java.sql.Connection</interfacename>
for meaningful values, but note that most databases do not support all isolation levels and some
define additional, non-standard isolations.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>1, 2, 4, 8</literal>
</para>
</entry>
@ -696,9 +696,9 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<property>hibernate.connection.autocommit</property>
</entry>
<entry>
Enables autocommit for JDBC pooled connections (not recommended).
Enables autocommit for JDBC pooled connections (it is not recommended).
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
@ -708,9 +708,9 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<property>hibernate.connection.release_mode</property>
</entry>
<entry>
Specify when Hibernate should release JDBC connections. By default,
Specifies when Hibernate should release JDBC connections. By default,
a JDBC connection is held until the session is explicitly closed or
disconnected. For an application server JTA datasource, you should use
disconnected. For an application server JTA datasource, use
<literal>after_statement</literal> to aggressively release connections
after every JDBC call. For a non-JTA connection, it often makes sense to
release the connection at the end of each transaction, by using
@ -719,12 +719,12 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
strategies and <literal>after_transaction</literal> for the JDBC
transaction strategy.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>auto</literal> (default) | <literal>on_close</literal> |
<literal>after_transaction</literal> | <literal>after_statement</literal>
</para>
<para>
Note that this setting only affects <literal>Session</literal>s returned from
This setting only affects <literal>Session</literal>s returned from
<literal>SessionFactory.openSession</literal>. For <literal>Session</literal>s
obtained through <literal>SessionFactory.getCurrentSession</literal>, the
<literal>CurrentSessionContext</literal> implementation configured for use
@ -774,7 +774,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<entry>
The classname of a custom <literal>CacheProvider</literal>.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>classname.of.CacheProvider</literal>
</para>
</entry>
@ -784,12 +784,12 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<literal>hibernate.cache.use_minimal_puts</literal>
</entry>
<entry>
Optimize second-level cache operation to minimize writes, at the
Optimizes second-level cache operation to minimize writes, at the
cost of more frequent reads. This setting is most useful for
clustered caches and, in Hibernate3, is enabled by default for
clustered cache implementations.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true|false</literal>
</para>
</entry>
@ -799,9 +799,9 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<literal>hibernate.cache.use_query_cache</literal>
</entry>
<entry>
Enable the query cache, individual queries still have to be set cachable.
Enables the query cache. Individual queries still have to be set cachable.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true|false</literal>
</para>
</entry>
@ -811,11 +811,11 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<literal>hibernate.cache.use_second_level_cache</literal>
</entry>
<entry>
May be used to completely disable the second level cache, which is enabled
Can be used to completely disable the second level cache, which is enabled
by default for classes which specify a <literal>&lt;cache&gt;</literal>
mapping.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true|false</literal>
</para>
</entry>
@ -828,7 +828,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
The classname of a custom <literal>QueryCache</literal> interface,
defaults to the built-in <literal>StandardQueryCache</literal>.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>classname.of.QueryCache</literal>
</para>
</entry>
@ -840,7 +840,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<entry>
A prefix to use for second-level cache region names.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>prefix</literal>
</para>
</entry>
@ -853,7 +853,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
Forces Hibernate to store data in the second-level cache
in a more human-friendly format.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true|false</literal>
</para>
</entry>
@ -883,7 +883,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
to use with Hibernate <literal>Transaction</literal> API
(defaults to <literal>JDBCTransactionFactory</literal>).
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>classname.of.TransactionFactory</literal>
</para>
</entry>
@ -897,7 +897,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
obtain the JTA <literal>UserTransaction</literal> from the
application server.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>jndi/composite/name</literal>
</para>
</entry>
@ -907,11 +907,11 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<literal>hibernate.transaction.manager_lookup_class</literal>
</entry>
<entry>
The classname of a <literal>TransactionManagerLookup</literal>
- required when JVM-level caching is enabled or when using hilo
The classname of a <literal>TransactionManagerLookup</literal>. It is
required when JVM-level caching is enabled or when using hilo
generator in a JTA environment.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>classname.of.TransactionManagerLookup</literal>
</para>
</entry>
@ -926,7 +926,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
automatic session context management is preferred, see
<xref linkend="architecture-current-session"/>.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
@ -938,10 +938,10 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<entry>
If enabled, the session will be automatically closed during the
after completion phase of the transaction. Built-in and
utomatic session context management is preferred, see
automatic session context management is preferred, see
<xref linkend="architecture-current-session"/>.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
@ -967,12 +967,12 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<literal>hibernate.current_session_context_class</literal>
</entry>
<entry>
Supply a (custom) strategy for the scoping of the "current"
Supply a custom strategy for the scoping of the "current"
<literal>Session</literal>. See
<xref linkend="architecture-current-session"/> for more
information about the built-in strategies.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>jta</literal> | <literal>thread</literal> |
<literal>managed</literal> | <literal>custom.Class</literal>
</para>
@ -985,7 +985,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<entry>
Chooses the HQL parser implementation.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>org.hibernate.hql.ast.ASTQueryTranslatorFactory</literal> or
<literal>org.hibernate.hql.classic.ClassicQueryTranslatorFactory</literal>
</para>
@ -996,10 +996,10 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<literal>hibernate.query.substitutions</literal>
</entry>
<entry>
Mapping from tokens in Hibernate queries to SQL tokens
Is used to map from tokens in Hibernate queries to SQL tokens
(tokens might be function or literal names, for example).
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC</literal>
</para>
</entry>
@ -1009,13 +1009,13 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<literal>hibernate.hbm2ddl.auto</literal>
</entry>
<entry>
Automatically validate or export schema DDL to the database
Automatically validates or exports schema DDL to the database
when the <literal>SessionFactory</literal> is created. With
<literal>create-drop</literal>, the database schema will be
dropped when the <literal>SessionFactory</literal> is closed
explicitly.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>validate</literal> | <literal>update</literal> |
<literal>create</literal> | <literal>create-drop</literal>
</para>
@ -1026,12 +1026,12 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<literal>hibernate.cglib.use_reflection_optimizer</literal>
</entry>
<entry>
Enables use of CGLIB instead of runtime reflection (System-level
property). Reflection can sometimes be useful when troubleshooting,
note that Hibernate always requires CGLIB even if you turn off the
optimizer. You can not set this property in <literal>hibernate.cfg.xml</literal>.
Enables the use of CGLIB instead of runtime reflection (System-level
property). Reflection can sometimes be useful when troubleshooting.
Hibernate always requires CGLIB even if you turn off the
optimizer. You cannot set this property in <literal>hibernate.cfg.xml</literal>.
<para>
<emphasis role="strong">eg.</emphasis>
<emphasis role="strong">e.g.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
@ -1044,10 +1044,10 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<title>SQL Dialects</title>
<para>
You should always set the <literal>hibernate.dialect</literal> property to the correct
Always set the <literal>hibernate.dialect</literal> property to the correct
<literal>org.hibernate.dialect.Dialect</literal> subclass for your database. If you
specify a dialect, Hibernate will use sensible defaults for some of the
other properties listed above, saving you the effort of specifying them manually.
other properties listed above. This means that you will not have to specify them manually.
</para>
<table frame="topbot" id="sql-dialects" revision="2">
@ -1142,17 +1142,17 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para>
If your database supports ANSI, Oracle or Sybase style outer joins, <emphasis>outer join
fetching</emphasis> will often increase performance by limiting the number of round
trips to and from the database (at the cost of possibly more work performed by
the database itself). Outer join fetching allows a whole graph of objects connected
trips to and from the database. This is, however, at the cost of possibly more work performed by
the database itself. Outer join fetching allows a whole graph of objects connected
by many-to-one, one-to-many, many-to-many and one-to-one associations to be retrieved
in a single SQL <literal>SELECT</literal>.
</para>
<para>
Outer join fetching may be disabled <emphasis>globally</emphasis> by setting
Outer join fetching can be disabled <emphasis>globally</emphasis> by setting
the property <literal>hibernate.max_fetch_depth</literal> to <literal>0</literal>.
A setting of <literal>1</literal> or higher enables outer join fetching for
one-to-one and many-to-one associations which have been mapped with
one-to-one and many-to-one associations that have been mapped with
<literal>fetch="join"</literal>.
</para>
@ -1166,8 +1166,8 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<title>Binary Streams</title>
<para>
Oracle limits the size of <literal>byte</literal> arrays that may
be passed to/from its JDBC driver. If you wish to use large instances of
Oracle limits the size of <literal>byte</literal> arrays that can
be passed to and/or from its JDBC driver. If you wish to use large instances of
<literal>binary</literal> or <literal>serializable</literal> type, you should
enable <literal>hibernate.jdbc.use_streams_for_binary</literal>.
<emphasis>This is a system-level setting only.</emphasis>
@ -1182,7 +1182,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
The properties prefixed by <literal>hibernate.cache</literal>
allow you to use a process or cluster scoped second-level cache system
with Hibernate. See the <xref linkend="performance-cache"/> for
more details.
more information.
</para>
</sect2>
@ -1191,21 +1191,21 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<title>Query Language Substitution</title>
<para>
You may define new Hibernate query tokens using <literal>hibernate.query.substitutions</literal>.
You can define new Hibernate query tokens using <literal>hibernate.query.substitutions</literal>.
For example:
</para>
<programlisting>hibernate.query.substitutions true=1, false=0</programlisting>
<para>
would cause the tokens <literal>true</literal> and <literal>false</literal> to be translated to
This would cause the tokens <literal>true</literal> and <literal>false</literal> to be translated to
integer literals in the generated SQL.
</para>
<programlisting>hibernate.query.substitutions toLowercase=LOWER</programlisting>
<para>
would allow you to rename the SQL <literal>LOWER</literal> function.
This would allow you to rename the SQL <literal>LOWER</literal> function.
</para>
</sect2>
@ -1214,8 +1214,8 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<title>Hibernate statistics</title>
<para>
If you enable <literal>hibernate.generate_statistics</literal>, Hibernate will
expose a number of metrics that are useful when tuning a running system via
If you enable <literal>hibernate.generate_statistics</literal>, Hibernate
exposes a number of metrics that are useful when tuning a running system via
<literal>SessionFactory.getStatistics()</literal>. Hibernate can even be configured
to expose these statistics via JMX. Read the Javadoc of the interfaces in
<literal>org.hibernate.stats</literal> for more information.
@ -1231,15 +1231,15 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
Hibernate utilizes <ulink url="http://www.slf4j.org/">Simple Logging Facade for Java</ulink>
(SLF4J) in order to log various system events. SLF4J can direct your logging output to
several logging frameworks (NOP, Simple, log4j version 1.2, JDK 1.4 logging, JCL or logback) depending on your
chosen binding. In order to setup logging properly you will need <filename>slf4j-api.jar</filename> in
chosen binding. In order to setup logging you will need <filename>slf4j-api.jar</filename> in
your classpath together with the jar file for your preferred binding - <filename>slf4j-log4j12.jar</filename>
in the case of Log4J. See the SLF4J <ulink url="http://www.slf4j.org/manual.html">documentation</ulink> for more detail.
To use Log4j you will also need to place a <filename>log4j.properties</filename> file in your classpath,
an example properties file is distributed with Hibernate in the <literal>src/</literal> directory.
To use Log4j you will also need to place a <filename>log4j.properties</filename> file in your classpath.
An example properties file is distributed with Hibernate in the <literal>src/</literal> directory.
</para>
<para>
We strongly recommend that you familiarize yourself with Hibernate's log
It is recommended that you familiarize yourself with Hibernate's log
messages. A lot of work has been put into making the Hibernate log as
detailed as possible, without making it unreadable. It is an essential
troubleshooting device. The most interesting log categories are the
@ -1302,8 +1302,8 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<row>
<entry><literal>org.hibernate</literal></entry>
<entry>
Log everything (a lot of information, but very useful for
troubleshooting)
Log everything. This is a lot of information but it is useful for
troubleshooting
</entry>
</row>
</tbody>
@ -1328,7 +1328,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</para>
<para>
You may provide rules for automatically generating database identifiers from
You can provide rules for automatically generating database identifiers from
Java identifiers or for processing "logical" column and table names given in
the mapping file into "physical" table and column names. This feature helps
reduce the verbosity of the mapping document, eliminating repetitive noise
@ -1337,7 +1337,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</para>
<para>
You may specify a different strategy by calling
You can specify a different strategy by calling
<literal>Configuration.setNamingStrategy()</literal> before adding mappings:
</para>
@ -1365,7 +1365,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</para>
<para>
The XML configuration file is by default expected to be in the root o
The XML configuration file is by default expected to be in the root of
your <literal>CLASSPATH</literal>. Here is an example:
</para>
@ -1403,22 +1403,22 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</hibernate-configuration>]]></programlisting>
<para>
As you can see, the advantage of this approach is the externalization of the
The advantage of this approach is the externalization of the
mapping file names to configuration. The <literal>hibernate.cfg.xml</literal>
is also more convenient once you have to tune the Hibernate cache. Note that is
is also more convenient once you have to tune the Hibernate cache. It is
your choice to use either <literal>hibernate.properties</literal> or
<literal>hibernate.cfg.xml</literal>, both are equivalent, except for the above
<literal>hibernate.cfg.xml</literal>. Both are equivalent, except for the above
mentioned benefits of using the XML syntax.
</para>
<para>
With the XML configuration, starting Hibernate is then as simple as
With the XML configuration, starting Hibernate is then as simple as:
</para>
<programlisting><![CDATA[SessionFactory sf = new Configuration().configure().buildSessionFactory();]]></programlisting>
<para>
You can pick a different XML configuration file using
You can select a different XML configuration file using:
</para>
<programlisting><![CDATA[SessionFactory sf = new Configuration()
@ -1441,8 +1441,8 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
JDBC connections managed by the container and provided through JNDI. Usually,
a JTA compatible <literal>TransactionManager</literal> and a
<literal>ResourceManager</literal> take care of transaction management (CMT),
esp. distributed transaction handling across several datasources. You may
of course also demarcate transaction boundaries programmatically (BMT) or
especially distributed transaction handling across several datasources. You can
also demarcate transaction boundaries programmatically (BMT), or
you might want to use the optional Hibernate <literal>Transaction</literal>
API for this to keep your code portable.
</para>
@ -1461,10 +1461,10 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<itemizedlist>
<listitem>
<para>
<emphasis>JTA Session binding:</emphasis> The Hibernate <literal>Session</literal>
may be automatically bound to the scope of JTA transactions. Simply
<emphasis>JTA Session binding:</emphasis> the Hibernate <literal>Session</literal>
can be automatically bound to the scope of JTA transactions. Simply
lookup the <literal>SessionFactory</literal> from JNDI and get the current
<literal>Session</literal>. Let Hibernate take care of flushing and closing the
<literal>Session</literal>. Let Hibernate manage flushing and closing the
<literal>Session</literal> when your JTA transaction completes. Transaction
demarcation is either declarative (CMT) or programmatic (BMT/UserTransaction).
</para>
@ -1474,12 +1474,12 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<itemizedlist>
<listitem>
<para>
<emphasis>JMX deployment:</emphasis> If you have a JMX capable application server
(e.g. JBoss AS), you can chose to deploy Hibernate as a managed MBean. This saves
<emphasis>JMX deployment:</emphasis> if you have a JMX capable application server
(e.g. JBoss AS), you can choose to deploy Hibernate as a managed MBean. This saves
you the one line startup code to build your <literal>SessionFactory</literal> from
a <literal>Configuration</literal>. The container will startup your
<literal>HibernateService</literal>, and ideally also take care of service
dependencies (Datasource has to be available before Hibernate starts, etc).
<literal>HibernateService</literal> and also take care of service
dependencies (datasource has to be available before Hibernate starts, etc).
</para>
</listitem>
</itemizedlist>
@ -1495,8 +1495,8 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para>
The Hibernate <literal>Session</literal> API is independent of any transaction
demarcation system in your architecture. If you let Hibernate use JDBC directly,
through a connection pool, you may begin and end your transactions by calling
demarcation system in your architecture. If you let Hibernate use JDBC directly
through a connection pool, you can begin and end your transactions by calling
the JDBC API. If you run in a J2EE application server, you might want to use bean-managed
transactions and call the JTA API and <literal>UserTransaction</literal> when needed.
</para>
@ -1509,7 +1509,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</para>
<para>
There are three standard (built-in) choices:
There are three standard, or built-in, choices:
</para>
<variablelist spacing="compact">
@ -1523,9 +1523,9 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<term><literal>org.hibernate.transaction.JTATransactionFactory</literal></term>
<listitem>
<para>
delegates to container-managed transaction if an existing transaction is
underway in this context (e.g. EJB session bean method), otherwise
a new transaction is started and bean-managed transaction are used.
delegates to container-managed transactions if an existing transaction is
underway in this context (for example, EJB session bean method). Otherwise,
a new transaction is started and bean-managed transactions are used.
</para>
</listitem>
</varlistentry>
@ -1538,15 +1538,15 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</variablelist>
<para>
You may also define your own transaction strategies (for a CORBA transaction service,
You can also define your own transaction strategies (for a CORBA transaction service,
for example).
</para>
<para>
Some features in Hibernate (i.e. the second level cache, Contextual Sessions with JTA, etc.)
Some features in Hibernate (i.e., the second level cache, Contextual Sessions with JTA, etc.)
require access to the JTA <literal>TransactionManager</literal> in a managed environment.
In an application server you have to specify how Hibernate should obtain a reference to the
<literal>TransactionManager</literal>, since J2EE does not standardize a single mechanism:
In an application server, since J2EE does not standardize a single mechanism, you have to specify how Hibernate should obtain a reference to the
<literal>TransactionManager</literal>:
</para>
<table frame="topbot" id="jtamanagerlookup" revision="1">
@ -1611,18 +1611,18 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<title>JNDI-bound <literal>SessionFactory</literal></title>
<para>
A JNDI bound Hibernate <literal>SessionFactory</literal> can simplify the lookup
of the factory and the creation of new <literal>Session</literal>s. Note that this
is not related to a JNDI bound <literal>Datasource</literal>, both simply use the
same registry!
A JNDI-bound Hibernate <literal>SessionFactory</literal> can simplify the lookup
function of the factory and create new <literal>Session</literal>s. This
is not, however, related to a JNDI bound <literal>Datasource</literal>; both simply use the
same registry.
</para>
<para>
If you wish to have the <literal>SessionFactory</literal> bound to a JNDI namespace, specify
a name (eg. <literal>java:hibernate/SessionFactory</literal>) using the property
a name (e.g. <literal>java:hibernate/SessionFactory</literal>) using the property
<literal>hibernate.session_factory_name</literal>. If this property is omitted, the
<literal>SessionFactory</literal> will not be bound to JNDI. (This is especially useful in
environments with a read-only JNDI default implementation, e.g. Tomcat.)
<literal>SessionFactory</literal> will not be bound to JNDI. This is especially useful in
environments with a read-only JNDI default implementation (in Tomcat, for example).
</para>
<para>
@ -1634,18 +1634,18 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para>
Hibernate will automatically place the <literal>SessionFactory</literal> in JNDI after
you call <literal>cfg.buildSessionFactory()</literal>. This means you will at least have
this call in some startup code (or utility class) in your application, unless you use
JMX deployment with the <literal>HibernateService</literal> (discussed later).
you call <literal>cfg.buildSessionFactory()</literal>. This means you will have
this call in some startup code, or utility class in your application, unless you use
JMX deployment with the <literal>HibernateService</literal> (this is discussed later in greater detail).
</para>
<para>
If you use a JNDI <literal>SessionFactory</literal>, an EJB or any other class may
obtain the <literal>SessionFactory</literal> using a JNDI lookup.
If you use a JNDI <literal>SessionFactory</literal>, an EJB or any other class, you can
obtain the <literal>SessionFactory</literal> using a JNDI lookup.
</para>
<para>
We recommend that you bind the <literal>SessionFactory</literal> to JNDI in
It is recommended that you bind the <literal>SessionFactory</literal> to JNDI in
a managed environment and use a <literal>static</literal> singleton otherwise.
To shield your application code from these details, we also recommend to hide the
actual lookup code for a <literal>SessionFactory</literal> in a helper class,
@ -1659,15 +1659,15 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<title>Current Session context management with JTA</title>
<para>
The easiest way to handle <literal>Session</literal>s and transactions is
Hibernates automatic "current" <literal>Session</literal> management.
See the discussion of <link linkend="architecture-current-session">current sessions</link>.
The easiest way to handle <literal>Sessions</literal> and transactions is
Hibernate's automatic "current" <literal>Session</literal> management.
For a discussion of contextual sessions see <link linkend="architecture-current-session"></link>.
Using the <literal>"jta"</literal> session context, if there is no Hibernate
<literal>Session</literal> associated with the current JTA transaction, one will
be started and associated with that JTA transaction the first time you call
<literal>sessionFactory.getCurrentSession()</literal>. The <literal>Session</literal>s
retrieved via <literal>getCurrentSession()</literal> in <literal>"jta"</literal> context
will be set to automatically flush before the transaction completes, close
retrieved via <literal>getCurrentSession()</literal> in the<literal>"jta"</literal> context
are set to automatically flush before the transaction completes, close
after the transaction completes, and aggressively release JDBC connections
after each statement. This allows the <literal>Session</literal>s to
be managed by the life cycle of the JTA transaction to which it is associated,
@ -1686,15 +1686,15 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para>
The line <literal>cfg.buildSessionFactory()</literal> still has to be executed
somewhere to get a <literal>SessionFactory</literal> into JNDI. You can do this
either in a <literal>static</literal> initializer block (like the one in
<literal>HibernateUtil</literal>) or you deploy Hibernate as a <emphasis>managed
either in a <literal>static</literal> initializer block, like the one in
<literal>HibernateUtil</literal>, or you can deploy Hibernate as a <emphasis>managed
service</emphasis>.
</para>
<para>
Hibernate is distributed with <literal>org.hibernate.jmx.HibernateService</literal>
for deployment on an application server with JMX capabilities, such as JBoss AS.
The actual deployment and configuration is vendor specific. Here is an example
The actual deployment and configuration is vendor-specific. Here is an example
<literal>jboss-service.xml</literal> for JBoss 4.0.x:
</para>
@ -1746,7 +1746,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
in a JAR file with the extension <literal>.sar</literal> (service archive). You also need
to package Hibernate, its required third-party libraries, your compiled persistent classes,
as well as your mapping files in the same archive. Your enterprise beans (usually session
beans) may be kept in their own JAR file, but you may include this EJB JAR file in the
beans) can be kept in their own JAR file, but you can include this EJB JAR file in the
main service archive to get a single (hot-)deployable unit. Consult the JBoss AS
documentation for more information about JMX service and EJB deployment.
</para>

View File

@ -29,9 +29,9 @@
<title>Interceptors and events</title>
<para>
It is often useful for the application to react to certain events that occur
inside Hibernate. This allows implementation of certain kinds of generic
functionality, and extension of Hibernate functionality.
It is useful for the application to react to certain events that occur
inside Hibernate. This allows for the implementation of generic
functionality and the extension of Hibernate functionality.
</para>
<sect1 id="objectstate-interceptors" revision="3">
@ -39,7 +39,7 @@
<para>
The <literal>Interceptor</literal> interface provides callbacks from the session to the
application allowing the application to inspect and/or manipulate properties of a
application, allowing the application to inspect and/or manipulate properties of a
persistent object before it is saved, updated, deleted or loaded. One
possible use for this is to track auditing information. For example, the following
<literal>Interceptor</literal> automatically sets the <literal>createTimestamp</literal>
@ -49,7 +49,7 @@
</para>
<para>
You may either implement <literal>Interceptor</literal> directly or (better) extend
You can either implement <literal>Interceptor</literal> directly or extend
<literal>EmptyInterceptor</literal>.
</para>
@ -137,7 +137,7 @@ public class AuditInterceptor extends EmptyInterceptor {
}]]></programlisting>
<para>
Interceptors come in two flavors: <literal>Session</literal>-scoped and
There are two kinds of inteceptors: <literal>Session</literal>-scoped and
<literal>SessionFactory</literal>-scoped.
</para>
@ -151,11 +151,11 @@ public class AuditInterceptor extends EmptyInterceptor {
<para>
A <literal>SessionFactory</literal>-scoped interceptor is registered with the <literal>Configuration</literal>
object prior to building the <literal>SessionFactory</literal>. In this case, the supplied interceptor
will be applied to all sessions opened from that <literal>SessionFactory</literal>; this is true unless
a session is opened explicitly specifying the interceptor to use. <literal>SessionFactory</literal>-scoped
interceptors must be thread safe, taking care to not store session-specific state since multiple
sessions will use this interceptor (potentially) concurrently.
object prior to building the <literal>SessionFactory</literal>. Unless
a session is opened explicitly specifying the interceptor to use, the supplied interceptor
will be applied to all sessions opened from that <literal>SessionFactory</literal>. <literal>SessionFactory</literal>-scoped
interceptors must be thread safe. Ensure that you do not store session-specific states, since multiple
sessions will use this interceptor potentially concurrently.
</para>
<programlisting><![CDATA[new Configuration().setInterceptor( new AuditInterceptor() );]]></programlisting>
@ -166,38 +166,38 @@ public class AuditInterceptor extends EmptyInterceptor {
<title>Event system</title>
<para>
If you have to react to particular events in your persistence layer, you may
If you have to react to particular events in your persistence layer, you can
also use the Hibernate3 <emphasis>event</emphasis> architecture. The event
system can be used in addition or as a replacement for interceptors.
system can be used in addition, or as a replacement, for interceptors.
</para>
<para>
Essentially all of the methods of the <literal>Session</literal> interface correlate
to an event. You have a <literal>LoadEvent</literal>, a <literal>FlushEvent</literal>, etc
(consult the XML configuration-file DTD or the <literal>org.hibernate.event</literal>
package for the full list of defined event types). When a request is made of one of
All the methods of the <literal>Session</literal> interface correlate
to an event. You have a <literal>LoadEvent</literal>, a <literal>FlushEvent</literal>, etc.
Consult the XML configuration-file DTD or the <literal>org.hibernate.event</literal>
package for the full list of defined event types. When a request is made of one of
these methods, the Hibernate <literal>Session</literal> generates an appropriate
event and passes it to the configured event listeners for that type. Out-of-the-box,
these listeners implement the same processing in which those methods always resulted.
However, you are free to implement a customization of one of the listener interfaces
(i.e., the <literal>LoadEvent</literal> is processed by the registered implemenation
(i.e., the <literal>LoadEvent</literal> is processed by the registered implementation
of the <literal>LoadEventListener</literal> interface), in which case their
implementation would be responsible for processing any <literal>load()</literal> requests
made of the <literal>Session</literal>.
</para>
<para>
The listeners should be considered effectively singletons; meaning, they are shared between
requests, and thus should not save any state as instance variables.
The listeners should be considered singletons. This means they are shared between
requests, and should not save any state as instance variables.
</para>
<para>
A custom listener should implement the appropriate interface for the event it wants to
A custom listener implements the appropriate interface for the event it wants to
process and/or extend one of the convenience base classes (or even the default event
listeners used by Hibernate out-of-the-box as these are declared non-final for this
purpose). Custom listeners can either be registered programmatically through the
<literal>Configuration</literal> object, or specified in the Hibernate configuration
XML (declarative configuration through the properties file is not supported). Here's an
XML. Declarative configuration through the properties file is not supported. Here is an
example of a custom load event listener:
</para>
@ -227,7 +227,7 @@ public class AuditInterceptor extends EmptyInterceptor {
</hibernate-configuration>]]></programlisting>
<para>
Instead, you may register it programmatically:
Instead, you can register it programmatically:
</para>
<programlisting><![CDATA[Configuration cfg = new Configuration();
@ -237,13 +237,13 @@ cfg.EventListeners().setLoadEventListeners(stack);]]></programlisting>
<para>
Listeners registered declaratively cannot share instances. If the same class name is
used in multiple <literal>&lt;listener/&gt;</literal> elements, each reference will
result in a separate instance of that class. If you need the capability to share
result in a separate instance of that class. If you need to share
listener instances between listener types you must use the programmatic registration
approach.
</para>
<para>
Why implement an interface and define the specific type during configuration? Well, a
Why implement an interface and define the specific type during configuration? A
listener implementation could implement multiple event listener interfaces. Having the
type additionally defined during registration makes it easier to turn custom listeners on
or off during configuration.
@ -255,8 +255,8 @@ cfg.EventListeners().setLoadEventListeners(stack);]]></programlisting>
<title>Hibernate declarative security</title>
<para>
Usually, declarative security in Hibernate applications is managed in a session facade
layer. Now, Hibernate3 allows certain actions to be permissioned via JACC, and authorized
via JAAS. This is optional functionality built on top of the event architecture.
layer. Hibernate3 allows certain actions to be permissioned via JACC, and authorized
via JAAS. This is an optional functionality that is built on top of the event architecture.
</para>
<para>
@ -270,13 +270,13 @@ cfg.EventListeners().setLoadEventListeners(stack);]]></programlisting>
<listener type="pre-load" class="org.hibernate.secure.JACCPreLoadEventListener"/>]]></programlisting>
<para>
Note that <literal>&lt;listener type="..." class="..."/&gt;</literal> is just a shorthand
Note that <literal>&lt;listener type="..." class="..."/&gt;</literal> is shorthand
for <literal>&lt;event type="..."&gt;&lt;listener class="..."/&gt;&lt;/event&gt;</literal>
when there is exactly one listener for a particular event type.
</para>
<para>
Next, still in <literal>hibernate.cfg.xml</literal>, bind the permissions to roles:
Next, while still in <literal>hibernate.cfg.xml</literal>, bind the permissions to roles:
</para>
<programlisting><![CDATA[<grant role="admin" entity-name="User" actions="insert,update,read"/>

View File

@ -27,9 +27,10 @@
<chapter id="example-mappings">
<title>Example: Various Mappings</title>
<para>
This chapters shows off some more complex association mappings.
This chapters explores some more complex association mappings.
</para>
<sect1 id="example-mappings-emp">
@ -37,8 +38,8 @@
<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
<literal>Employee</literal> uses an entity class (<literal>Employment</literal>)
to represent the association. You can do this when there might be more than one
period of employment for the same two parties. Components are used to model monetary
values and employee names.
</para>
@ -53,7 +54,7 @@
</mediaobject>
<para>
Heres a possible mapping document:
Here is a possible mapping document:
</para>
<programlisting><![CDATA[<hibernate-mapping>
@ -106,7 +107,7 @@
</hibernate-mapping>]]></programlisting>
<para>
And heres the table schema generated by <literal>SchemaExport</literal>.
Here is the table schema generated by <literal>SchemaExport</literal>.
</para>
<programlisting><![CDATA[create table employers (
@ -150,10 +151,10 @@ create sequence employer_id_seq]]></programlisting>
<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
<literal>Author</literal> and <literal>Person</literal>. In the example, the relationship
between <literal>Work</literal> and <literal>Author</literal> is represented as a many-to-many
association and the relationship between <literal>Author</literal>
and <literal>Person</literal> is represented as one-to-one association. Another possibility would be to
have <literal>Author</literal> extend <literal>Person</literal>.
</para>
@ -223,11 +224,11 @@ create sequence employer_id_seq]]></programlisting>
</hibernate-mapping>]]></programlisting>
<para>
There are four tables in this mapping. <literal>works</literal>,
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>.
table linking authors to works. Here is the table schema, as generated by
<literal>SchemaExport</literal>:
</para>
<programlisting><![CDATA[create table works (
@ -271,14 +272,14 @@ alter table author_work
<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>.
In this section we consider a model of the relationships between <literal>Customer</literal>,
<literal>Order</literal>, <literal>Line Item</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
<literal>Order</literal>, but how can you represent <literal>Order</literal> /
<literal>LineItem</literal> / <literal>Product</literal>? In the example,
<literal>LineItem</literal> is mapped 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.
Hibernate this is called a composite element.
</para>
<mediaobject>
@ -291,7 +292,7 @@ alter table author_work
</mediaobject>
<para>
The mapping document:
The mapping document will look like this:
</para>
<programlisting><![CDATA[<hibernate-mapping>
@ -379,12 +380,12 @@ alter table line_items
<title>Miscellaneous example mappings</title>
<para>
These examples are all taken from the Hibernate test suite. You
will find many other useful example mappings there. Look in the
These examples are available from the Hibernate test suite. You
will find many other useful example mappings there by searching in the
<literal>test</literal> folder of the Hibernate distribution.
</para>
<para>TODO: put words around this stuff</para>
<!-- <<para>TODO: put words around this stuff</para>-->
<sect2 id="example-mappings-typed-onetone">
<title>"Typed" one-to-one association</title>

View File

@ -29,36 +29,36 @@
<title>Example: Parent/Child</title>
<para>
One of the very first things that new users try to do with Hibernate is to model a parent / child type
relationship. There are two different approaches to this. For various reasons the most convenient
One of the first things that new users want to do with Hibernate is to model a parent/child type
relationship. There are two different approaches to this. The most convenient
approach, especially for new users, is to model both <literal>Parent</literal> and <literal>Child</literal>
as entity classes with a <literal>&lt;one-to-many&gt;</literal> association from <literal>Parent</literal>
to <literal>Child</literal>. (The alternative approach is to declare the <literal>Child</literal> as a
<literal>&lt;composite-element&gt;</literal>.) Now, it turns out that default semantics of a one to many
association (in Hibernate) are much less close to the usual semantics of a parent / child relationship than
those of a composite element mapping. We will explain how to use a <emphasis>bidirectional one to many
association with cascades</emphasis> to model a parent / child relationship efficiently and elegantly.
It's not at all difficult!
to <literal>Child</literal>. The alternative approach is to declare the <literal>Child</literal> as a
<literal>&lt;composite-element&gt;</literal>. The default semantics of a one-to-many
association in Hibernate are much less close to the usual semantics of a parent/child relationship than
those of a composite element mapping. We will explain how to use a <emphasis>bidirectional one-to-many
association with cascades</emphasis> to model a parent/child relationship efficiently and elegantly.
</para>
<sect1 id="example-parentchild-collections">
<title>A note about collections</title>
<para>
Hibernate collections are considered to be a logical part of their owning entity; never of the
contained entities. This is a crucial distinction! It has the following consequences:
Hibernate collections are considered to be a logical part of their owning entity and not of the
contained entities. Be aware that this is a critical distinction that has the following consequences:
</para>
<itemizedlist>
<listitem>
<para>
When we remove / add an object from / to a collection, the version number of the collection owner
When you remove/add an object from/to a collection, the version number of the collection owner
is incremented.
</para>
</listitem>
<listitem>
<para>
If an object that was removed from a collection is an instance of a value type (eg, a composite
If an object that was removed from a collection is an instance of a value type (e.g. a composite
element), that object will cease to be persistent and its state will be completely removed from
the database. Likewise, adding a value type instance to the collection will cause its state to be
immediately persistent.
@ -66,9 +66,9 @@
</listitem>
<listitem>
<para>
On the other hand, if an entity is removed from a collection (a one-to-many or many-to-many
association), it will not be deleted, by default. This behaviour is completely consistent - a
change to the internal state of another entity should not cause the associated entity to vanish!
Conversely, if an entity is removed from a collection (a one-to-many or many-to-many
association), it will not be deleted by default. This behavior is completely consistent; a
change to the internal state of another entity should not cause the associated entity to vanish.
Likewise, adding an entity to a collection does not cause that entity to become persistent, by
default.
</para>
@ -76,9 +76,9 @@
</itemizedlist>
<para>
Instead, the default behaviour is that adding an entity to a collection merely creates a link between
the two entities, while removing it removes the link. This is very appropriate for all sorts of cases.
Where it is not appropriate at all is the case of a parent / child relationship, where the life of the
Adding an entity to a collection, by default, merely creates a link between
the two entities. Removing the entity will remove the link. This is appropriate for all sorts of cases.
However, it is not appropriate in the case of a parent/child relationship. In this case, the life of the
child is bound to the life cycle of the parent.
</para>
@ -98,7 +98,7 @@
</set>]]></programlisting>
<para>
If we were to execute the following code
If we were to execute the following code:
</para>
<programlisting><![CDATA[Parent p = .....;
@ -125,7 +125,7 @@ session.flush();]]></programlisting>
<para>
This is not only inefficient, but also violates any <literal>NOT NULL</literal> constraint on the
<literal>parent_id</literal> column. We can fix the nullability constraint violation by specifying
<literal>parent_id</literal> column. You can fix the nullability constraint violation by specifying
<literal>not-null="true"</literal> in the collection mapping:
</para>
@ -138,21 +138,21 @@ session.flush();]]></programlisting>
However, this is not the recommended solution.
</para>
<para>
The underlying cause of this behaviour is that the link (the foreign key <literal>parent_id</literal>)
The underlying cause of this behavior is that the link (the foreign key <literal>parent_id</literal>)
from <literal>p</literal> to <literal>c</literal> is not considered part of the state of the
<literal>Child</literal> object and is therefore not created in the <literal>INSERT</literal>. So the
<literal>Child</literal> object and is therefore not created in the <literal>INSERT</literal>. The
solution is to make the link part of the <literal>Child</literal> mapping.
</para>
<programlisting><![CDATA[<many-to-one name="parent" column="parent_id" not-null="true"/>]]></programlisting>
<para>
(We also need to add the <literal>parent</literal> property to the <literal>Child</literal> class.)
You also need to add the <literal>parent</literal> property to the <literal>Child</literal> class.
</para>
<para>
Now that the <literal>Child</literal> entity is managing the state of the link, we tell the collection
not to update the link. We use the <literal>inverse</literal> attribute.
not to update the link. We use the <literal>inverse</literal> attribute to do this:
</para>
<programlisting><![CDATA[<set name="children" inverse="true">
@ -161,7 +161,7 @@ session.flush();]]></programlisting>
</set>]]></programlisting>
<para>
The following code would be used to add a new <literal>Child</literal>
The following code would be used to add a new <literal>Child</literal>:
</para>
<programlisting><![CDATA[Parent p = (Parent) session.load(Parent.class, pid);
@ -172,11 +172,11 @@ session.save(c);
session.flush();]]></programlisting>
<para>
And now, only one SQL <literal>INSERT</literal> would be issued!
Only one SQL <literal>INSERT</literal> would now be issued.
</para>
<para>
To tighten things up a bit, we could create an <literal>addChild()</literal> method of
You could also create an <literal>addChild()</literal> method of
<literal>Parent</literal>.
</para>
@ -186,7 +186,7 @@ session.flush();]]></programlisting>
}]]></programlisting>
<para>
Now, the code to add a <literal>Child</literal> looks like
The code to add a <literal>Child</literal> looks like this:
</para>
<programlisting><![CDATA[Parent p = (Parent) session.load(Parent.class, pid);
@ -201,7 +201,7 @@ session.flush();]]></programlisting>
<title>Cascading life cycle</title>
<para>
The explicit call to <literal>save()</literal> is still annoying. We will address this by
You can address the frustrations of the explicit call to <literal>save()</literal> by
using cascades.
</para>
@ -211,7 +211,7 @@ session.flush();]]></programlisting>
</set>]]></programlisting>
<para>
This simplifies the code above to
This simplifies the code above to:
</para>
<programlisting><![CDATA[Parent p = (Parent) session.load(Parent.class, pid);
@ -220,7 +220,7 @@ p.addChild(c);
session.flush();]]></programlisting>
<para>
Similarly, we don't need to iterate over the children when saving or deleting a <literal>Parent</literal>.
Similarly, we do not need to iterate over the children when saving or deleting a <literal>Parent</literal>.
The following removes <literal>p</literal> and all its children from the database.
</para>
@ -229,7 +229,7 @@ session.delete(p);
session.flush();]]></programlisting>
<para>
However, this code
However, the following code:
</para>
<programlisting><![CDATA[Parent p = (Parent) session.load(Parent.class, pid);
@ -239,8 +239,8 @@ c.setParent(null);
session.flush();]]></programlisting>
<para>
will not remove <literal>c</literal> from the database; it will ony remove the link to <literal>p</literal>
(and cause a <literal>NOT NULL</literal> constraint violation, in this case). You need to explicitly
will not remove <literal>c</literal> from the database. In this case, it will only remove the link to <literal>p</literal>
and cause a <literal>NOT NULL</literal> constraint violation. You need to explicitly
<literal>delete()</literal> the <literal>Child</literal>.
</para>
@ -251,8 +251,8 @@ session.delete(c);
session.flush();]]></programlisting>
<para>
Now, in our case, a <literal>Child</literal> can't really exist without its parent. So if we remove
a <literal>Child</literal> from the collection, we really do want it to be deleted. For this, we must
In our case, a <literal>Child</literal> cannot exist without its parent. So if we remove
a <literal>Child</literal> from the collection, we do want it to be deleted. To do this, we must
use <literal>cascade="all-delete-orphan"</literal>.
</para>
@ -262,8 +262,8 @@ session.flush();]]></programlisting>
</set>]]></programlisting>
<para>
Note: even though the collection mapping specifies <literal>inverse="true"</literal>, cascades are
still processed by iterating the collection elements. So if you require that an object be saved,
Even though the collection mapping specifies <literal>inverse="true"</literal>, cascades are
still processed by iterating the collection elements. If you need an object be saved,
deleted or updated by cascade, you must add it to the collection. It is not enough to simply call
<literal>setParent()</literal>.
</para>
@ -275,10 +275,10 @@ session.flush();]]></programlisting>
<para>
Suppose we loaded up a <literal>Parent</literal> in one <literal>Session</literal>, made some changes
in a UI action and wish to persist these changes in a new session by calling <literal>update()</literal>.
The <literal>Parent</literal> will contain a collection of childen and, since cascading update is enabled,
in a UI action and wanted to persist these changes in a new session by calling <literal>update()</literal>.
The <literal>Parent</literal> will contain a collection of children and, since the cascading update is enabled,
Hibernate needs to know which children are newly instantiated and which represent existing rows in the
database. Lets assume that both <literal>Parent</literal> and <literal>Child</literal> have genenerated
database. We will also assume that both <literal>Parent</literal> and <literal>Child</literal> have generated
identifier properties of type <literal>Long</literal>. Hibernate will use the identifier and
version/timestamp property value to determine which of the children are new. (See
<xref linkend="objectstate-saveorupdate"/>.) <emphasis>In Hibernate3, it is no longer necessary to specify
@ -287,7 +287,7 @@ session.flush();]]></programlisting>
<para>
The following code will update <literal>parent</literal> and <literal>child</literal> and insert
<literal>newChild</literal>.
<literal>newChild</literal>:
</para>
<programlisting><![CDATA[//parent and child were both loaded in a previous session
@ -298,9 +298,9 @@ session.update(parent);
session.flush();]]></programlisting>
<para>
Well, that's all very well for the case of a generated identifier, but what about assigned identifiers
and composite identifiers? This is more difficult, since Hibernate can't use the identifier property to
distinguish between a newly instantiated object (with an identifier assigned by the user) and an
This may be suitable for the case of a generated identifier, but what about assigned identifiers
and composite identifiers? This is more difficult, since Hibernate cannot use the identifier property to
distinguish between a newly instantiated object, with an identifier assigned by the user, and an
object loaded in a previous session. In this case, Hibernate will either use the timestamp or version
property, or will actually query the second-level cache or, worst case, the database, to see if the
row exists.
@ -363,7 +363,7 @@ public boolean onSave(Object entity,
}]]></programlisting>
<para>
Don't worry; in Hibernate3 you don't need to write any of this kind of code if you don't want to.
Do not worry; in Hibernate3 you do not need to write any of this kind of code if you do not want to.
</para>
-->
</sect1>
@ -372,15 +372,15 @@ public boolean onSave(Object entity,
<title>Conclusion</title>
<para>
There is quite a bit to digest here and it might look confusing first time around. However, in practice,
it all works out very nicely. Most Hibernate applications use the parent / child pattern in many places.
The sections we have just covered can be a bit confusing. However, in practice,
it all works out nicely. Most Hibernate applications use the parent/child pattern in many places.
</para>
<para>
We mentioned an alternative in the first paragraph. None of the above issues exist in the case of
<literal>&lt;composite-element&gt;</literal> mappings, which have exactly the semantics of a parent / child
relationship. Unfortunately, there are two big limitations to composite element classes: composite elements
may not own collections, and they should not be the child of any entity other than the unique parent.
<literal>&lt;composite-element&gt;</literal> mappings, which have exactly the semantics of a parent/child
relationship. Unfortunately, there are two big limitations with composite element classes: composite elements
cannot own collections and they should not be the child of any entity other than the unique parent.
</para>
</sect1>

View File

@ -32,9 +32,9 @@
<title>Persistent Classes</title>
<para>
The persistent classes represent a weblog, and an item posted
The persistent classes here represent a weblog and an item posted
in a weblog. They are to be modelled as a standard parent/child
relationship, but we will use an ordered bag, instead of a set.
relationship, but we will use an ordered bag, instead of a set:
</para>
<programlisting><![CDATA[package eg;
@ -116,7 +116,7 @@ public class BlogItem {
<title>Hibernate Mappings</title>
<para>
The XML mappings should now be quite straightforward.
The XML mappings are now straightforward. For example:
</para>
<programlisting><![CDATA[<?xml version="1.0"?>
@ -210,7 +210,7 @@ public class BlogItem {
<para>
The following class demonstrates some of the kinds of things
we can do with these classes, using Hibernate.
we can do with these classes using Hibernate:
</para>
<programlisting><![CDATA[package eg;

View File

@ -30,7 +30,7 @@
<para>
Hibernate3 provides an innovative new approach to handling data with "visibility" rules.
A <emphasis>Hibernate filter</emphasis> is a global, named, parameterized filter that may be
A <emphasis>Hibernate filter</emphasis> is a global, named, parameterized filter that can be
enabled or disabled for a particular Hibernate session.
</para>
@ -38,12 +38,12 @@
<title>Hibernate filters</title>
<para>
Hibernate3 adds the ability to pre-define filter criteria and attach those filters at both
a class and a collection level. A filter criteria is the ability to define a restriction clause
very similiar to the existing "where" attribute available on the class and various collection
elements. Except these filter conditions can be parameterized. The application can then make
the decision at runtime whether given filters should be enabled and what their parameter
values should be. Filters can be used like database views, but parameterized inside the
Hibernate3 has the ability to pre-define filter criteria and attach those filters at both
a class level and a collection level. A filter criteria allows you to define a restriction clause
similar to the existing "where" attribute available on the class and various collection
elements. These filter conditions, however, can be parameterized. The application can then
decide at runtime whether certain filters should be enabled and what their parameter
values should be. Filters can be used like database views, but they are parameterized inside the
application.
</para>
@ -58,7 +58,7 @@
</filter-def>]]></programlisting>
<para>
Then, this filter can be attached to a class:
This filter can then be attached to a class:
</para>
<programlisting><![CDATA[<class name="myClass" ...>
@ -67,7 +67,7 @@
</class>]]></programlisting>
<para>
or, to a collection:
Or, to a collection:
</para>
<programlisting><![CDATA[<set ...>
@ -75,26 +75,26 @@
</set>]]></programlisting>
<para>
or, even to both (or multiples of each) at the same time.
Or, to both or multiples of each at the same time.
</para>
<para>
The methods on <literal>Session</literal> are: <literal>enableFilter(String filterName)</literal>,
<literal>getEnabledFilter(String filterName)</literal>, and <literal>disableFilter(String filterName)</literal>.
By default, filters are <emphasis>not</emphasis> enabled for a given session; they must be explcitly
By default, filters are <emphasis>not</emphasis> enabled for a given session. Filters must be
enabled through use of the <literal>Session.enableFilter()</literal> method, which returns an
instance of the <literal>Filter</literal> interface. Using the simple filter defined above, this
would look like:
instance of the <literal>Filter</literal> interface. If you used the simple filter defined above, it would
look like this:
</para>
<programlisting><![CDATA[session.enableFilter("myFilter").setParameter("myFilterParam", "some-value");]]></programlisting>
<para>
Note that methods on the org.hibernate.Filter interface do allow the method-chaining common to much of Hibernate.
Methods on the org.hibernate.Filter interface do allow the method-chaining common to much of Hibernate.
</para>
<para>
A full example, using temporal data with an effective record date pattern:
The following is a full example, using temporal data with an effective record date pattern:
</para>
<programlisting><![CDATA[<filter-def name="effectiveDate">
@ -126,7 +126,7 @@
</class>]]></programlisting>
<para>
Then, in order to ensure that you always get back currently effective records, simply
In order to ensure that you are provided with currently effective records,
enable the filter on the session prior to retrieving employee data:
</para>
@ -138,32 +138,32 @@ List results = session.createQuery("from Employee as e where e.salary > :targetS
]]></programlisting>
<para>
In the HQL above, even though we only explicitly mentioned a salary constraint on the results,
because of the enabled filter the query will return only currently active employees who have
a salary greater than a million dollars.
Even though a salary constraint was mentioned explicitly on the results in the above HQL,
because of the enabled filter, the query will return only currently active employees who have
a salary greater than one million dollars.
</para>
<para>
Note: if you plan on using filters with outer joining (either through HQL or load fetching) be
careful of the direction of the condition expression. Its safest to set this up for left
outer joining; in general, place the parameter first followed by the column name(s) after
If you want to use filters with outer joining, either through HQL or load fetching, be
careful of the direction of the condition expression. It is safest to set this up for left
outer joining. Place the parameter first followed by the column name(s) after
the operator.
</para>
<para>
After being defined a filter might be attached to multiple entities and/or
collections each with its own condition. That can be tedious when the
conditions are the same each time. Thus <literal>&lt;filter-def/&gt;</literal>
allows defining a default condition, either as an attribute or CDATA:
After being defined, a filter might be attached to multiple entities and/or
collections each with its own condition. This can be problematic when the
conditions are the same each time. Using <literal>&lt;filter-def/&gt;</literal>
allows you to definine a default condition, either as an attribute or CDATA:
</para>
<programlisting><![CDATA[<filter-def name="myFilter" condition="abc > xyz">...</filter-def>
<filter-def name="myOtherFilter">abc=xyz</filter-def>]]></programlisting>
<para>
This default condition will then be used whenever the filter is attached to something
without specifying a condition. Note that this means you can give a specific condition
as part of the attachment of the filter which overrides the default condition in that
This default condition will be used whenever the filter is attached to something
without specifying a condition. This means you can give a specific condition
as part of the attachment of the filter that overrides the default condition in that
particular case.
</para>

View File

@ -26,10 +26,10 @@
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="inheritance">
<title>Inheritance Mapping</title>
<title>Inheritance mapping</title>
<sect1 id="inheritance-strategies" revision="3">
<title>The Three Strategies</title>
<title>The three strategies</title>
<para>
Hibernate supports the three basic inheritance mapping strategies:
@ -68,25 +68,25 @@
<para>
It is possible to use different mapping strategies for different
branches of the same inheritance hierarchy, and then make use of implicit
branches of the same inheritance hierarchy. You can then make use of implicit
polymorphism to achieve polymorphism across the whole hierarchy. However,
Hibernate does not support mixing <literal>&lt;subclass&gt;</literal>,
and <literal>&lt;joined-subclass&gt;</literal> and
<literal>&lt;joined-subclass&gt;</literal> and
<literal>&lt;union-subclass&gt;</literal> mappings under the same root
<literal>&lt;class&gt;</literal> element. It is possible to mix together
the table per hierarchy and table per subclass strategies, under the
the table per hierarchy and table per subclass strategies under the
the same <literal>&lt;class&gt;</literal> element, by combining the
<literal>&lt;subclass&gt;</literal> and <literal>&lt;join&gt;</literal>
elements (see below).
elements (see below for an example).
</para>
<para>
It is possible to define <literal>subclass</literal>, <literal>union-subclass</literal>,
and <literal>joined-subclass</literal> mappings in separate mapping documents, directly beneath
<literal>hibernate-mapping</literal>. This allows you to extend a class hierachy just by adding
and <literal>joined-subclass</literal> mappings in separate mapping documents directly beneath
<literal>hibernate-mapping</literal>. This allows you to extend a class hierarchy by adding
a new mapping file. You must specify an <literal>extends</literal> attribute in the subclass mapping,
naming a previously mapped superclass. Note: Previously this feature made the ordering of the mapping
documents important. Since Hibernate3, the ordering of mapping files does not matter when using the
naming a previously mapped superclass. Previously this feature made the ordering of the mapping
documents important. Since Hibernate3, the ordering of mapping files is irrelevant when using the
extends keyword. The ordering inside a single mapping file still needs to be defined as superclasses
before subclasses.
</para>
@ -103,10 +103,10 @@
<title>Table per class hierarchy</title>
<para>
Suppose we have an interface <literal>Payment</literal>, with implementors
Suppose we have an interface <literal>Payment</literal> with the implementors
<literal>CreditCardPayment</literal>, <literal>CashPayment</literal>,
<literal>ChequePayment</literal>. The table per hierarchy mapping would
look like:
and <literal>ChequePayment</literal>. The table per hierarchy mapping would
display in the following way:
</para>
<programlisting><![CDATA[<class name="Payment" table="PAYMENT">
@ -129,9 +129,9 @@
</class>]]></programlisting>
<para>
Exactly one table is required. There is one big limitation of this mapping
Exactly one table is required. There is a limitation of this mapping
strategy: columns declared by the subclasses, such as <literal>CCTYPE</literal>,
may not have <literal>NOT NULL</literal> constraints.
cannot have <literal>NOT NULL</literal> constraints.
</para>
</sect2>
@ -140,7 +140,7 @@
<title>Table per subclass</title>
<para>
A table per subclass mapping would look like:
A table per subclass mapping looks like this:
</para>
<programlisting><![CDATA[<class name="Payment" table="PAYMENT">
@ -166,25 +166,25 @@
<para>
Four tables are required. The three subclass tables have primary
key associations to the superclass table (so the relational model
is actually a one-to-one association).
key associations to the superclass table so the relational model
is actually a one-to-one association.
</para>
</sect2>
<sect2 id="inheritance-tablepersubclass-discriminator" revision="2">
<title>Table per subclass, using a discriminator</title>
<title>Table per subclass: using a discriminator</title>
<para>
Note that Hibernate's implementation of table per subclass requires
no discriminator column. Other object/relational mappers use a
different implementation of table per subclass which requires a type
Hibernate's implementation of table per subclass
does not require a discriminator column. Other object/relational mappers use a
different implementation of table per subclass that requires a type
discriminator column in the superclass table. The approach taken by
Hibernate is much more difficult to implement but arguably more
correct from a relational point of view. If you would like to use
Hibernate is much more difficult to implement, but arguably more
correct from a relational point of view. If you want to use
a discriminator column with the table per subclass strategy, you
may combine the use of <literal>&lt;subclass&gt;</literal> and
<literal>&lt;join&gt;</literal>, as follow:
can combine the use of <literal>&lt;subclass&gt;</literal> and
<literal>&lt;join&gt;</literal>, as follows:
</para>
<programlisting><![CDATA[<class name="Payment" table="PAYMENT">
@ -227,8 +227,8 @@
<title>Mixing table per class hierarchy with table per subclass</title>
<para>
You may even mix the table per hierarchy and table per subclass strategies
using this approach:
You can even mix the table per hierarchy and table per subclass strategies
using the following approach:
</para>
<programlisting><![CDATA[<class name="Payment" table="PAYMENT">
@ -266,8 +266,8 @@
<title>Table per concrete class</title>
<para>
There are two ways we could go about mapping the table per concrete class
strategy. The first is to use <literal>&lt;union-subclass&gt;</literal>.
There are two ways we can map the table per concrete class
strategy. First, you can use <literal>&lt;union-subclass&gt;</literal>.
</para>
<programlisting><![CDATA[<class name="Payment">
@ -296,23 +296,23 @@
<para>
The limitation of this approach is that if a property is mapped on the
superclass, the column name must be the same on all subclass tables.
(We might relax this in a future release of Hibernate.) The identity
generator strategy is not allowed in union subclass inheritance, indeed
the primary key seed has to be shared accross all unioned subclasses
of a hierarchy.
The identity generator strategy is not allowed in union subclass inheritance.
The primary key seed has to be shared across all unioned subclasses
of a hierarchy.
</para>
<para>
If your superclass is abstract, map it with <literal>abstract="true"</literal>.
Of course, if it is not abstract, an additional table (defaults to
<literal>PAYMENT</literal> in the example above) is needed to hold instances
If it is not abstract, an additional table (it defaults to
<literal>PAYMENT</literal> in the example above), is needed to hold instances
of the superclass.
</para>
</sect2>
<sect2 id="inheritance-tableperconcreate-polymorphism">
<title>Table per concrete class, using implicit polymorphism</title>
<title>Table per concrete class using implicit polymorphism</title>
<para>
An alternative approach is to make use of implicit polymorphism:
@ -343,12 +343,12 @@
</class>]]></programlisting>
<para>
Notice that nowhere do we mention the <literal>Payment</literal> interface
explicitly. Also notice that properties of <literal>Payment</literal> are
Notice that the <literal>Payment</literal> interface
is not mentioned explicitly. Also notice that properties of <literal>Payment</literal> are
mapped in each of the subclasses. If you want to avoid duplication, consider
using XML entities
(e.g. <literal>[ &lt;!ENTITY allproperties SYSTEM "allproperties.xml"&gt; ]</literal>
in the <literal>DOCTYPE</literal> declartion and
(for example, <literal>[ &lt;!ENTITY allproperties SYSTEM "allproperties.xml"&gt; ]</literal>
in the <literal>DOCTYPE</literal> declaration and
<literal>&amp;allproperties;</literal> in the mapping).
</para>
@ -372,15 +372,15 @@
</sect2>
<sect2 id="inheritace-mixingpolymorphism">
<sect2 id="inheritance-mixingpolymorphism">
<title>Mixing implicit polymorphism with other inheritance mappings</title>
<para>
There is one further thing to notice about this mapping. Since the subclasses
are each mapped in their own <literal>&lt;class&gt;</literal> element (and since
Since the subclasses
are each mapped in their own <literal>&lt;class&gt;</literal> element, and since
<literal>Payment</literal> is just an interface), each of the subclasses could
easily be part of another inheritance hierarchy! (And you can still use polymorphic
queries against the <literal>Payment</literal> interface.)
easily be part of another inheritance hierarchy. You can still use polymorphic
queries against the <literal>Payment</literal> interface.
</para>
<programlisting><![CDATA[<class name="CreditCardPayment" table="CREDIT_PAYMENT">
@ -412,12 +412,12 @@
</class>]]></programlisting>
<para>
Once again, we don't mention <literal>Payment</literal> explicitly. If we
execute a query against the <literal>Payment</literal> interface - for
example, <literal>from Payment</literal> - Hibernate
Once again, <literal>Payment</literal> is not mentioned explicitly. If we
execute a query against the <literal>Payment</literal> interface, for
example <literal>from Payment</literal>, Hibernate
automatically returns instances of <literal>CreditCardPayment</literal>
(and its subclasses, since they also implement <literal>Payment</literal>),
<literal>CashPayment</literal> and <literal>ChequePayment</literal> but
<literal>CashPayment</literal> and <literal>ChequePayment</literal>, but
not instances of <literal>NonelectronicTransaction</literal>.
</para>
@ -429,7 +429,7 @@
<title>Limitations</title>
<para>
There are certain limitations to the "implicit polymorphism" approach to
There are limitations to the "implicit polymorphism" approach to
the table per concrete-class mapping strategy. There are somewhat less
restrictive limitations to <literal>&lt;union-subclass&gt;</literal>
mappings.

View File

@ -32,9 +32,9 @@
<title>Fetching strategies</title>
<para>
A <emphasis>fetching strategy</emphasis> is the strategy Hibernate will use for
retrieving associated objects if the application needs to navigate the association.
Fetch strategies may be declared in the O/R mapping metadata, or over-ridden by a
Hibernate uses a <emphasis>fetching strategy</emphasis> to
retrieve associated objects if the application needs to navigate the association.
Fetch strategies can be declared in the O/R mapping metadata, or over-ridden by a
particular HQL or <literal>Criteria</literal> query.
</para>
@ -45,35 +45,35 @@
<itemizedlist>
<listitem>
<para>
<emphasis>Join fetching</emphasis> - Hibernate retrieves the
<emphasis>Join fetching</emphasis>: Hibernate retrieves the
associated instance or collection in the same <literal>SELECT</literal>,
using an <literal>OUTER JOIN</literal>.
</para>
</listitem>
<listitem>
<para>
<emphasis>Select fetching</emphasis> - a second <literal>SELECT</literal>
<emphasis>Select fetching</emphasis>: a second <literal>SELECT</literal>
is used to retrieve the associated entity or collection. Unless
you explicitly disable lazy fetching by specifying <literal>lazy="false"</literal>,
this second select will only be executed when you actually access the
this second select will only be executed when you access the
association.
</para>
</listitem>
<listitem>
<para>
<emphasis>Subselect fetching</emphasis> - a second <literal>SELECT</literal>
<emphasis>Subselect fetching</emphasis>: a second <literal>SELECT</literal>
is used to retrieve the associated collections for all entities retrieved in a
previous query or fetch. Unless you explicitly disable lazy fetching by specifying
<literal>lazy="false"</literal>, this second select will only be executed when you
actually access the association.
access the association.
</para>
</listitem>
<listitem>
<para>
<emphasis>Batch fetching</emphasis> - an optimization strategy
for select fetching - Hibernate retrieves a batch of entity instances
or collections in a single <literal>SELECT</literal>, by specifying
a list of primary keys or foreign keys.
<emphasis>Batch fetching</emphasis>: an optimization strategy
for select fetching. Hibernate retrieves a batch of entity instances
or collections in a single <literal>SELECT</literal> by specifying
a list of primary or foreign keys.
</para>
</listitem>
</itemizedlist>
@ -85,45 +85,45 @@
<itemizedlist>
<listitem>
<para>
<emphasis>Immediate fetching</emphasis> - an association, collection or
attribute is fetched immediately, when the owner is loaded.
<emphasis>Immediate fetching</emphasis>: an association, collection or
attribute is fetched immediately when the owner is loaded.
</para>
</listitem>
<listitem>
<para>
<emphasis>Lazy collection fetching</emphasis> - a collection is fetched
when the application invokes an operation upon that collection. (This
is the default for collections.)
<emphasis>Lazy collection fetching</emphasis>: a collection is fetched
when the application invokes an operation upon that collection. This
is the default for collections.
</para>
</listitem>
<listitem>
<para>
<emphasis>"Extra-lazy" collection fetching</emphasis> - individual
<emphasis>"Extra-lazy" collection fetching</emphasis>: individual
elements of the collection are accessed from the database as needed.
Hibernate tries not to fetch the whole collection into memory unless
absolutely needed (suitable for very large collections)
absolutely needed. It is suitable for large collections.
</para>
</listitem>
<listitem>
<para>
<emphasis>Proxy fetching</emphasis> - a single-valued association is
<emphasis>Proxy fetching</emphasis>: a single-valued association is
fetched when a method other than the identifier getter is invoked
upon the associated object.
</para>
</listitem>
<listitem>
<para>
<emphasis>"No-proxy" fetching</emphasis> - a single-valued association is
<emphasis>"No-proxy" fetching</emphasis>: a single-valued association is
fetched when the instance variable is accessed. Compared to proxy fetching,
this approach is less lazy (the association is fetched even when only the
identifier is accessed) but more transparent, since no proxy is visible to
this approach is less lazy; the association is fetched even when only the
identifier is accessed. It is also more transparent, since no proxy is visible to
the application. This approach requires buildtime bytecode instrumentation
and is rarely necessary.
</para>
</listitem>
<listitem>
<para>
<emphasis>Lazy attribute fetching</emphasis> - an attribute or single
<emphasis>Lazy attribute fetching</emphasis>: an attribute or single
valued association is fetched when the instance variable is accessed.
This approach requires buildtime bytecode instrumentation and is rarely
necessary.
@ -133,8 +133,8 @@
<para>
We have two orthogonal notions here: <emphasis>when</emphasis> is the association
fetched, and <emphasis>how</emphasis> is it fetched (what SQL is used). Don't
confuse them! We use <literal>fetch</literal> to tune performance. We may use
fetched and <emphasis>how</emphasis> is it fetched. It is important that you do not
confuse them. We use <literal>fetch</literal> to tune performance. We can use
<literal>lazy</literal> to define a contract for what data is always available
in any detached instance of a particular class.
</para>
@ -144,19 +144,19 @@
<para>
By default, Hibernate3 uses lazy select fetching for collections and lazy proxy
fetching for single-valued associations. These defaults make sense for almost
all associations in almost all applications.
fetching for single-valued associations. These defaults make sense for most
associations in the majority of applications.
</para>
<para>
<emphasis>Note:</emphasis> if you set
If you set
<literal>hibernate.default_batch_fetch_size</literal>, Hibernate will use the
batch fetch optimization for lazy fetching (this optimization may also be enabled
at a more granular level).
batch fetch optimization for lazy fetching. This optimization can also be enabled
at a more granular level.
</para>
<para>
However, lazy fetching poses one problem that you must be aware of. Access to a
Please be aware that access to a
lazy association outside of the context of an open Hibernate session will result
in an exception. For example:
</para>
@ -177,22 +177,22 @@ Integer accessLevel = (Integer) permissions.get("accounts"); // Error!]]></prog
Since the permissions collection was not initialized when the
<literal>Session</literal> was closed, the collection will not be able to
load its state. <emphasis>Hibernate does not support lazy initialization
for detached objects</emphasis>. The fix is to move the code that reads
for detached objects</emphasis>. This can be fixed by moving the code that reads
from the collection to just before the transaction is committed.
</para>
<para>
Alternatively, we could use a non-lazy collection or association,
Alternatively, you can use a non-lazy collection or association,
by specifying <literal>lazy="false"</literal> for the association mapping.
However, it is intended that lazy initialization be used for almost all
collections and associations. If you define too many non-lazy associations
in your object model, Hibernate will end up needing to fetch the entire
database into memory in every transaction!
in your object model, Hibernate will fetch the entire
database into memory in every transaction.
</para>
<para>
On the other hand, we often want to choose join fetching (which is non-lazy by
nature) instead of select fetching in a particular transaction. We'll now see
On the other hand, you can use join fetching, which is non-lazy by
nature, instead of select fetching in a particular transaction. We will now explain
how to customize the fetching strategy. In Hibernate3, the mechanisms for
choosing a fetch strategy are identical for single-valued associations and
collections.
@ -244,13 +244,13 @@ Integer accessLevel = (Integer) permissions.get("accounts"); // Error!]]></prog
</itemizedlist>
<para>
No matter what fetching strategy you use, the defined non-lazy graph is guaranteed
to be loaded into memory. Note that this might result in several immediate selects
Irrespective of the fetching strategy you use, the defined non-lazy graph is guaranteed
to be loaded into memory. This might, however, result in several immediate selects
being used to execute a particular HQL query.
</para>
<para>
Usually, we don't use the mapping document to customize fetching. Instead, we
Usually, the mapping document is not used to customize fetching. Instead, we
keep the default behavior, and override it for a particular transaction, using
<literal>left join fetch</literal> in HQL. This tells Hibernate to fetch
the association eagerly in the first select, using an outer join. In the
@ -259,9 +259,9 @@ Integer accessLevel = (Integer) permissions.get("accounts"); // Error!]]></prog
</para>
<para>
If you ever feel like you wish you could change the fetching strategy used by
<literal>get()</literal> or <literal>load()</literal>, simply use a
<literal>Criteria</literal> query, for example:
If you want to change the fetching strategy used by
<literal>get()</literal> or <literal>load()</literal>, you can use a
<literal>Criteria</literal> query. For example:
</para>
<programlisting><![CDATA[User user = (User) session.createCriteria(User.class)
@ -270,11 +270,11 @@ Integer accessLevel = (Integer) permissions.get("accounts"); // Error!]]></prog
.uniqueResult();]]></programlisting>
<para>
(This is Hibernate's equivalent of what some ORM solutions call a "fetch plan".)
This is Hibernate's equivalent of what some ORM solutions call a "fetch plan".
</para>
<para>
A completely different way to avoid problems with N+1 selects is to use the
A completely different approach to problems with N+1 selects is to use the
second-level cache.
</para>
@ -288,11 +288,11 @@ Integer accessLevel = (Integer) permissions.get("accounts"); // Error!]]></prog
of persistent collections. However, a different mechanism is needed for lazy
behavior in single-ended associations. The target entity of the association must
be proxied. Hibernate implements lazy initializing proxies for persistent objects
using runtime bytecode enhancement (via the excellent CGLIB library).
using runtime bytecode enhancement which is accessed via the CGLIB library.
</para>
<para>
By default, Hibernate3 generates proxies (at startup) for all persistent classes
At startup, Hibernate3 generates proxies by default for all persistent classes
and uses them to enable lazy fetching of <literal>many-to-one</literal> and
<literal>one-to-one</literal> associations.
</para>
@ -300,13 +300,12 @@ Integer accessLevel = (Integer) permissions.get("accounts"); // Error!]]></prog
<para>
The mapping file may declare an interface to use as the proxy interface for that
class, with the <literal>proxy</literal> attribute. By default, Hibernate uses a subclass
of the class. <emphasis>Note that the proxied class must implement a default constructor
with at least package visibility. We recommend this constructor for all persistent classes!</emphasis>
of the class. <emphasis>The proxied class must implement a default constructor
with at least package visibility. This constructor is recommended for all persistent classes</emphasis>.
</para>
<para>
There are some gotchas to be aware of when extending this approach to polymorphic
classes, eg.
There are potential problems to note when extending this approach to polymorphic classes.For example:
</para>
<programlisting><![CDATA[<class name="Cat" proxy="Cat">
@ -329,7 +328,7 @@ if ( cat.isDomesticCat() ) { // hit the db to initialize the pr
}]]></programlisting>
<para>
Secondly, it is possible to break proxy <literal>==</literal>.
Secondly, it is possible to break proxy <literal>==</literal>:
</para>
<programlisting><![CDATA[Cat cat = (Cat) session.load(Cat.class, id); // instantiate a Cat proxy
@ -346,20 +345,22 @@ System.out.println(cat==dc); // false]]></programlist
System.out.println( dc.getWeight() ); // 11.0]]></programlisting>
<para>
Third, you may not use a CGLIB proxy for a <literal>final</literal> class or a class
Third, you cannot use a CGLIB proxy for a <literal>final</literal> class or a class
with any <literal>final</literal> methods.
</para>
<para>
Finally, if your persistent object acquires any resources upon instantiation (eg. in
Finally, if your persistent object acquires any resources upon instantiation (e.g. in
initializers or default constructor), then those resources will also be acquired by
the proxy. The proxy class is an actual subclass of the persistent class.
</para>
<para>
These problems are all due to fundamental limitations in Java's single inheritance model.
If you wish to avoid these problems your persistent classes must each implement an interface
that declares its business methods. You should specify these interfaces in the mapping file. eg.
To avoid these problems your persistent classes must each implement an interface
that declares its business methods. You should specify these interfaces in the mapping file where
<literal>CatImpl</literal> implements the interface <literal>Cat</literal> and <literal>DomesticCatImpl</literal>
implements the interface <literal>DomesticCat</literal>. For example:
</para>
<programlisting><![CDATA[<class name="CatImpl" proxy="Cat">
@ -370,36 +371,40 @@ System.out.println( dc.getWeight() ); // 11.0]]></programlisting>
</class>]]></programlisting>
<para>
where <literal>CatImpl</literal> implements the interface <literal>Cat</literal> and
<literal>DomesticCatImpl</literal> implements the interface <literal>DomesticCat</literal>. Then
proxies for instances of <literal>Cat</literal> and <literal>DomesticCat</literal> may be returned
by <literal>load()</literal> or <literal>iterate()</literal>. (Note that <literal>list()</literal>
does not usually return proxies.)
Then proxies for instances of <literal>Cat</literal> and <literal>DomesticCat</literal> can be returned
by <literal>load()</literal> or <literal>iterate()</literal>.
</para>
<programlisting><![CDATA[Cat cat = (Cat) session.load(CatImpl.class, catid);
Iterator iter = session.createQuery("from CatImpl as cat where cat.name='fritz'").iterate();
Cat fritz = (Cat) iter.next();]]></programlisting>
<para>
<note><title>Note</title>
<para>
<literal>list()</literal> does not usually return proxies.
</para>
</note>
<para>
Relationships are also lazily initialized. This means you must declare any properties to be of
type <literal>Cat</literal>, not <literal>CatImpl</literal>.
</para>
<para>
Certain operations do <emphasis>not</emphasis> require proxy initialization
Certain operations do <emphasis>not</emphasis> require proxy initialization:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
<literal>equals()</literal>, if the persistent class does not override
<literal>equals()</literal>: if the persistent class does not override
<literal>equals()</literal>
</para>
</listitem>
<listitem>
<para>
<literal>hashCode()</literal>, if the persistent class does not override
<literal>hashCode()</literal>: if the persistent class does not override
<literal>hashCode()</literal>
</para>
</listitem>
@ -417,8 +422,8 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<para>
By choosing <literal>lazy="no-proxy"</literal> instead of the default
<literal>lazy="proxy"</literal>, we can avoid the problems associated with typecasting.
However, we will require buildtime bytecode instrumentation, and all operations
<literal>lazy="proxy"</literal>, you can avoid problems associated with typecasting.
However, buildtime bytecode instrumentation is required, and all operations
will result in immediate proxy initialization.
</para>
@ -429,19 +434,19 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<para>
A <literal>LazyInitializationException</literal> will be thrown by Hibernate if an uninitialized
collection or proxy is accessed outside of the scope of the <literal>Session</literal>, ie. when
collection or proxy is accessed outside of the scope of the <literal>Session</literal>, i.e., when
the entity owning the collection or having the reference to the proxy is in the detached state.
</para>
<para>
Sometimes we need to ensure that a proxy or collection is initialized before closing the
<literal>Session</literal>. Of course, we can alway force initialization by calling
Sometimes a proxy or collection needs to be initialized before closing the
<literal>Session</literal>. You can force initialization by calling
<literal>cat.getSex()</literal> or <literal>cat.getKittens().size()</literal>, for example.
But that is confusing to readers of the code and is not convenient for generic code.
However, this can be confusing to readers of the code and it is not convenient for generic code.
</para>
<para>
The static methods <literal>Hibernate.initialize()</literal> and <literal>Hibernate.isInitialized()</literal>
The static methods <literal>Hibernate.initialize()</literal> and <literal>Hibernate.isInitialized()</literal>,
provide the application with a convenient way of working with lazily initialized collections or
proxies. <literal>Hibernate.initialize(cat)</literal> will force the initialization of a proxy,
<literal>cat</literal>, as long as its <literal>Session</literal> is still open.
@ -450,7 +455,7 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
</para>
<para>
Another option is to keep the <literal>Session</literal> open until all needed
Another option is to keep the <literal>Session</literal> open until all required
collections and proxies have been loaded. In some application architectures,
particularly where the code that accesses data using Hibernate, and the code that
uses it are in different application layers or different physical processes, it
@ -462,7 +467,7 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<listitem>
<para>
In a web-based application, a servlet filter can be used to close the
<literal>Session</literal> only at the very end of a user request, once
<literal>Session</literal> only at the end of a user request, once
the rendering of the view is complete (the <emphasis>Open Session in
View</emphasis> pattern). Of course, this places heavy demands on the
correctness of the exception handling of your application infrastructure.
@ -475,7 +480,7 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<listitem>
<para>
In an application with a separate business tier, the business logic must
"prepare" all collections that will be needed by the web tier before
"prepare" all collections that the web tier needs before
returning. This means that the business tier should load all the data and
return all the data already initialized to the presentation/web tier that
is required for a particular use case. Usually, the application calls
@ -489,18 +494,18 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
</listitem>
<listitem>
<para>
You may also attach a previously loaded object to a new <literal>Session</literal>
You can also attach a previously loaded object to a new <literal>Session</literal>
with <literal>merge()</literal> or <literal>lock()</literal> before
accessing uninitialized collections (or other proxies). No, Hibernate does not,
and certainly <emphasis>should</emphasis> not do this automatically, since it
would introduce ad hoc transaction semantics!
accessing uninitialized collections or other proxies. Hibernate does not,
and certainly <emphasis>should</emphasis> not, do this automatically since it
would introduce impromptu transaction semantics.
</para>
</listitem>
</itemizedlist>
<para>
Sometimes you don't want to initialize a large collection, but still need some
information about it (like its size) or a subset of the data.
Sometimes you do not want to initialize a large collection, but still need some
information about it, like its size, for example, or a subset of the data.
</para>
<para>
@ -522,29 +527,29 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<title>Using batch fetching</title>
<para>
Hibernate can make efficient use of batch fetching, that is, Hibernate can load several uninitialized
proxies if one proxy is accessed (or collections. Batch fetching is an optimization of the lazy select
fetching strategy. There are two ways you can tune batch fetching: on the class and the collection level.
Using batch fetching, Hibernate can load several uninitialized
proxies if one proxy is accessed. Batch fetching is an optimization of the lazy select
fetching strategy. There are two ways you can configure batch fetching: on the class level and the collection level.
</para>
<para>
Batch fetching for classes/entities is easier to understand. Imagine you have the following situation
at runtime: You have 25 <literal>Cat</literal> instances loaded in a <literal>Session</literal>, each
Batch fetching for classes/entities is easier to understand. Consider the following example:
at runtime you have 25 <literal>Cat</literal> instances loaded in a <literal>Session</literal>, and each
<literal>Cat</literal> has a reference to its <literal>owner</literal>, a <literal>Person</literal>.
The <literal>Person</literal> class is mapped with a proxy, <literal>lazy="true"</literal>. If you now
iterate through all cats and call <literal>getOwner()</literal> on each, Hibernate will by default
execute 25 <literal>SELECT</literal> statements, to retrieve the proxied owners. You can tune this
iterate through all cats and call <literal>getOwner()</literal> on each, Hibernate will, by default,
execute 25 <literal>SELECT</literal> statements to retrieve the proxied owners. You can tune this
behavior by specifying a <literal>batch-size</literal> in the mapping of <literal>Person</literal>:
</para>
<programlisting><![CDATA[<class name="Person" batch-size="10">...</class>]]></programlisting>
<para>
Hibernate will now execute only three queries, the pattern is 10, 10, 5.
Hibernate will now execute only three queries: the pattern is 10, 10, 5.
</para>
<para>
You may also enable batch fetching of collections. For example, if each <literal>Person</literal> has
You can also enable batch fetching of collections. For example, if each <literal>Person</literal> has
a lazy collection of <literal>Cat</literal>s, and 10 persons are currently loaded in the
<literal>Session</literal>, iterating through all persons will generate 10 <literal>SELECT</literal>s,
one for every call to <literal>getCats()</literal>. If you enable batch fetching for the
@ -565,9 +570,9 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
</para>
<para>
Batch fetching of collections is particularly useful if you have a nested tree of items, ie.
the typical bill-of-materials pattern. (Although a <emphasis>nested set</emphasis> or a
<emphasis>materialized path</emphasis> might be a better option for read-mostly trees.)
Batch fetching of collections is particularly useful if you have a nested tree of items, i.e.
the typical bill-of-materials pattern. However, a <emphasis>nested set</emphasis> or a
<emphasis>materialized path</emphasis> might be a better option for read-mostly trees.
</para>
</sect2>
@ -576,9 +581,9 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<title>Using subselect fetching</title>
<para>
If one lazy collection or single-valued proxy has to be fetched, Hibernate loads all of
If one lazy collection or single-valued proxy has to be fetched, Hibernate will load all of
them, re-running the original query in a subselect. This works in the same way as
batch-fetching, without the piecemeal loading.
batch-fetching but without the piecemeal loading.
</para>
<!-- TODO: Write more about this -->
@ -591,10 +596,10 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<para>
Hibernate3 supports the lazy fetching of individual properties. This optimization technique
is also known as <emphasis>fetch groups</emphasis>. Please note that this is mostly a
marketing feature, as in practice, optimizing row reads is much more important than
optimization of column reads. However, only loading some properties of a class might
be useful in extreme cases, when legacy tables have hundreds of columns and the data model
can not be improved.
marketing feature; optimizing row reads is much more important than
optimization of column reads. However, only loading some properties of a class could
be useful in extreme cases. For example, when legacy tables have hundreds of columns and the data model
cannot be improved.
</para>
<para>
@ -612,9 +617,9 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
</class>]]></programlisting>
<para>
Lazy property loading requires buildtime bytecode instrumentation! If your persistent
classes are not enhanced, Hibernate will silently ignore lazy property settings and
fall back to immediate fetching.
Lazy property loading requires buildtime bytecode instrumentation. If your persistent
classes are not enhanced, Hibernate will ignore lazy property settings and
return to immediate fetching.
</para>
<para>
@ -636,14 +641,14 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
</target>]]></programlisting>
<para>
A different (better?) way to avoid unnecessary column reads, at least for
read-only transactions is to use the projection features of HQL or Criteria
A different way of avoiding unnecessary column reads, at least for
read-only transactions, is to use the projection features of HQL or Criteria
queries. This avoids the need for buildtime bytecode processing and is
certainly a preferred solution.
</para>
<para>
You may force the usual eager fetching of properties using <literal>fetch all
You can force the usual eager fetching of properties using <literal>fetch all
properties</literal> in HQL.
</para>
@ -657,19 +662,19 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<para>
A Hibernate <literal>Session</literal> is a transaction-level cache of persistent data. It is
possible to configure a cluster or JVM-level (<literal>SessionFactory</literal>-level) cache on
a class-by-class and collection-by-collection basis. You may even plug in a clustered cache. Be
careful. Caches are never aware of changes made to the persistent store by another application
(though they may be configured to regularly expire cached data).
a class-by-class and collection-by-collection basis. You can even plug in a clustered cache. Be
aware that caches are not aware of changes made to the persistent store by another application.
They can, however, be configured to regularly expire cached data.
</para>
<para revision="1">
You have the option to tell Hibernate which caching implementation to use by
specifying the name of a class that implements <literal>org.hibernate.cache.CacheProvider</literal>
using the property <literal>hibernate.cache.provider_class</literal>. Hibernate
comes bundled with a number of built-in integrations with open-source cache providers
(listed below); additionally, you could implement your own and plug it in as
outlined above. Note that versions prior to 3.2 defaulted to use EhCache as the
default cache provider; that is no longer the case as of 3.2.
is bundled with a number of built-in integrations with the open-source cache providers
that are listed below. You can also implement your own and plug it in as
outlined above. Note that versions prior to 3.2 use EhCache as the default
cache provider.
</para>
<table frame="topbot" id="cacheproviders" revision="1">
@ -767,16 +772,16 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
</callout>
<callout arearefs="cache2">
<para>
<literal>region</literal> (optional, defaults to the class or
collection role name) specifies the name of the second level cache
<literal>region</literal> (optional: defaults to the class or
collection role name): specifies the name of the second level cache
region
</para>
</callout>
<callout arearefs="cache3">
<para>
<literal>include</literal> (optional, defaults to <literal>all</literal>)
<literal>non-lazy</literal> specifies that properties of the entity mapped
with <literal>lazy="true"</literal> may not be cached when attribute-level
<literal>include</literal> (optional: defaults to <literal>all</literal>)
<literal>non-lazy</literal>: specifies that properties of the entity mapped
with <literal>lazy="true"</literal> cannot be cached when attribute-level
lazy fetching is enabled
</para>
</callout>
@ -784,7 +789,7 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
</programlistingco>
<para>
Alternatively (preferably?), you may specify <literal>&lt;class-cache&gt;</literal> and
Alternatively, you can specify <literal>&lt;class-cache&gt;</literal> and
<literal>&lt;collection-cache&gt;</literal> elements in <literal>hibernate.cfg.xml</literal>.
</para>
@ -798,9 +803,9 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<title>Strategy: read only</title>
<para>
If your application needs to read but never modify instances of a persistent class, a
<literal>read-only</literal> cache may be used. This is the simplest and best performing
strategy. It's even perfectly safe for use in a cluster.
If your application needs to read, but not modify, instances of a persistent class, a
<literal>read-only</literal> cache can be used. This is the simplest and optimal performing
strategy. It is even safe for use in a cluster.
</para>
<programlisting><![CDATA[<class name="eg.Immutable" mutable="false">
@ -818,11 +823,11 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
If the application needs to update data, a <literal>read-write</literal> cache might be appropriate.
This cache strategy should never be used if serializable transaction isolation level is required.
If the cache is used in a JTA environment, you must specify the property
<literal>hibernate.transaction.manager_lookup_class</literal>, naming a strategy for obtaining the
<literal>hibernate.transaction.manager_lookup_class</literal> and naming a strategy for obtaining the
JTA <literal>TransactionManager</literal>. In other environments, you should ensure that the transaction
is completed when <literal>Session.close()</literal> or <literal>Session.disconnect()</literal> is called.
If you wish to use this strategy in a cluster, you should ensure that the underlying cache implementation
supports locking. The built-in cache providers do <emphasis>not</emphasis>.
If you want to use this strategy in a cluster, you should ensure that the underlying cache implementation
supports locking. The built-in cache providers <emphasis>do not</emphasis> support locking.
</para>
<programlisting><![CDATA[<class name="eg.Cat" .... >
@ -840,8 +845,8 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<title>Strategy: nonstrict read/write</title>
<para>
If the application only occasionally needs to update data (ie. if it is extremely unlikely that two
transactions would try to update the same item simultaneously) and strict transaction isolation is
If the application only occasionally needs to update data (i.e. if it is extremely unlikely that two
transactions would try to update the same item simultaneously), and strict transaction isolation is
not required, a <literal>nonstrict-read-write</literal> cache might be appropriate. If the cache is
used in a JTA environment, you must specify <literal>hibernate.transaction.manager_lookup_class</literal>.
In other environments, you should ensure that the transaction is completed when
@ -855,7 +860,7 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<para>
The <literal>transactional</literal> cache strategy provides support for fully transactional cache
providers such as JBoss TreeCache. Such a cache may only be used in a JTA environment and you must
providers such as JBoss TreeCache. Such a cache can only be used in a JTA environment and you must
specify <literal>hibernate.transaction.manager_lookup_class</literal>.
</para>
@ -947,16 +952,16 @@ Cat fritz = (Cat) iter.next();]]></programlisting>
<para>
Whenever you pass an object to <literal>save()</literal>, <literal>update()</literal>
or <literal>saveOrUpdate()</literal> and whenever you retrieve an object using
or <literal>saveOrUpdate()</literal>, and whenever you retrieve an object using
<literal>load()</literal>, <literal>get()</literal>, <literal>list()</literal>,
<literal>iterate()</literal> or <literal>scroll()</literal>, that object is added
to the internal cache of the <literal>Session</literal>.
</para>
<para>
When <literal>flush()</literal> is subsequently called, the state of that object will
be synchronized with the database. If you do not want this synchronization to occur or
be synchronized with the database. If you do not want this synchronization to occur, or
if you are processing a huge number of objects and need to manage memory efficiently,
the <literal>evict()</literal> method may be used to remove the object and its collections
the <literal>evict()</literal> method can be used to remove the object and its collections
from the first-level cache.
</para>
@ -973,7 +978,7 @@ while ( cats.next() ) {
</para>
<para>
To completely evict all objects from the session cache, call <literal>Session.clear()</literal>
To evict all objects from the session cache, call <literal>Session.clear()</literal>
</para>
<para>
@ -989,31 +994,31 @@ sessionFactory.evictCollection("Cat.kittens"); //evict all kitten collections]]>
<para>
The <literal>CacheMode</literal> controls how a particular session interacts with the second-level
cache.
cache:
</para>
<itemizedlist>
<listitem>
<para>
<literal>CacheMode.NORMAL</literal> - read items from and write items to the second-level cache
<literal>CacheMode.NORMAL</literal>: will read items from and write items to the second-level cache
</para>
</listitem>
<listitem>
<para>
<literal>CacheMode.GET</literal> - read items from the second-level cache, but don't write to
<literal>CacheMode.GET</literal>: will read items from the second-level cache. Do not write to
the second-level cache except when updating data
</para>
</listitem>
<listitem>
<para>
<literal>CacheMode.PUT</literal> - write items to the second-level cache, but don't read from
<literal>CacheMode.PUT</literal>: will write items to the second-level cache. Do not read from
the second-level cache
</para>
</listitem>
<listitem>
<para>
<literal>CacheMode.REFRESH</literal> - write items to the second-level cache, but don't read from
the second-level cache, bypass the effect of <literal>hibernate.cache.use_minimal_puts</literal>, forcing
<literal>CacheMode.REFRESH</literal>: will write items to the second-level cache. Do not read from
the second-level cache. Bypass the effect of <literal>hibernate.cache.use_minimal_puts</literal> forcing
a refresh of the second-level cache for all items read from the database
</para>
</listitem>
@ -1029,8 +1034,8 @@ sessionFactory.evictCollection("Cat.kittens"); //evict all kitten collections]]>
.getEntries();]]></programlisting>
<para>
You'll need to enable statistics, and, optionally, force Hibernate to keep the cache entries in a
more human-understandable format:
You will need to enable statistics and, optionally, force Hibernate to keep the cache entries in a
more readable format:
</para>
<programlisting><![CDATA[hibernate.generate_statistics true
@ -1042,31 +1047,31 @@ hibernate.cache.use_structured_entries true]]></programlisting>
<title>The Query Cache</title>
<para>
Query result sets may also be cached. This is only useful for queries that are run
frequently with the same parameters. To use the query cache you must first enable it:
Query result sets can also be cached. This is only useful for queries that are run
frequently with the same parameters. You will first need to enable the query cache:
</para>
<programlisting><![CDATA[hibernate.cache.use_query_cache true]]></programlisting>
<para>
This setting causes the creation of two new cache regions - one holding cached query
This setting creates two new cache regions: one holding cached query
result sets (<literal>org.hibernate.cache.StandardQueryCache</literal>), the other
holding timestamps of the most recent updates to queryable tables
(<literal>org.hibernate.cache.UpdateTimestampsCache</literal>). Note that the query
cache does not cache the state of the actual entities in the result set; it caches
only identifier values and results of value type. So the query cache should always be
only identifier values and results of value type. The query cache should always be
used in conjunction with the second-level cache.
</para>
<para>
Most queries do not benefit from caching, so by default queries are not cached. To
Most queries do not benefit from caching, so by default, queries are not cached. To
enable caching, call <literal>Query.setCacheable(true)</literal>. This call allows
the query to look for existing cache results or add its results to the cache when
it is executed.
</para>
<para>
If you require fine-grained control over query cache expiration policies, you may
If you require fine-grained control over query cache expiration policies, you can
specify a named cache region for a particular query by calling
<literal>Query.setCacheRegion()</literal>.
</para>
@ -1093,9 +1098,9 @@ hibernate.cache.use_structured_entries true]]></programlisting>
<title>Understanding Collection performance</title>
<para>
We've already spent quite some time talking about collections.
In this section we will highlight a couple more issues about
how collections behave at runtime.
In the previous sections we have covered collections and their applications.
In this section we explore some more issues in relation to
collections at runtime.
</para>
<sect2 id="performance-collections-taxonomy">
@ -1108,10 +1113,10 @@ hibernate.cache.use_structured_entries true]]></programlisting>
<para>collections of values</para>
</listitem>
<listitem>
<para>one to many associations</para>
<para>one-to-many associations</para>
</listitem>
<listitem>
<para>many to many associations</para>
<para>many-to-many associations</para>
</listitem>
</itemizedlist>
@ -1137,42 +1142,42 @@ hibernate.cache.use_structured_entries true]]></programlisting>
</itemizedlist>
<para>
All indexed collections (maps, lists, arrays) have a primary key consisting
All indexed collections (maps, lists, and arrays) have a primary key consisting
of the <literal>&lt;key&gt;</literal> and <literal>&lt;index&gt;</literal>
columns. In this case collection updates are usually extremely efficient -
the primary key may be efficiently indexed and a particular row may be efficiently
columns. In this case, collection updates are extremely efficient.
The primary key can be efficiently indexed and a particular row can be efficiently
located when Hibernate tries to update or delete it.
</para>
<para>
Sets have a primary key consisting of <literal>&lt;key&gt;</literal> and element
columns. This may be less efficient for some types of collection element, particularly
composite elements or large text or binary fields; the database may not be able to index
a complex primary key as efficiently. On the other hand, for one to many or many to many
columns. This can be less efficient for some types of collection element, particularly
composite elements or large text or binary fields, as the database may not be able to index
a complex primary key as efficiently. However, for one-to-many or many-to-many
associations, particularly in the case of synthetic identifiers, it is likely to be just
as efficient. (Side-note: if you want <literal>SchemaExport</literal> to actually create
the primary key of a <literal>&lt;set&gt;</literal> for you, you must declare all columns
as <literal>not-null="true"</literal>.)
as efficient. If you want <literal>SchemaExport</literal> to actually create
the primary key of a <literal>&lt;set&gt;</literal>, you must declare all columns
as <literal>not-null="true"</literal>.
</para>
<para>
<literal>&lt;idbag&gt;</literal> mappings define a surrogate key, so they are
always very efficient to update. In fact, they are the best case.
efficient to update. In fact, they are the best case.
</para>
<para>
Bags are the worst case. Since a bag permits duplicate element values and has no
index column, no primary key may be defined. Hibernate has no way of distinguishing
Bags are the worst case since they permit duplicate element values and, as they have no
index column, no primary key can be defined. Hibernate has no way of distinguishing
between duplicate rows. Hibernate resolves this problem by completely removing
(in a single <literal>DELETE</literal>) and recreating the collection whenever it
changes. This might be very inefficient.
in a single <literal>DELETE</literal> and recreating the collection whenever it
changes. This can be inefficient.
</para>
<para>
Note that for a one-to-many association, the "primary key" may not be the physical
primary key of the database table - but even in this case, the above classification
is still useful. (It still reflects how Hibernate "locates" individual rows of the
collection.)
For a one-to-many association, the "primary key" may not be the physical
primary key of the database table. Even in this case, the above classification
is still useful. It reflects how Hibernate "locates" individual rows of the
collection.
</para>
</sect2>
@ -1182,29 +1187,29 @@ hibernate.cache.use_structured_entries true]]></programlisting>
<para>
From the discussion above, it should be clear that indexed collections
and (usually) sets allow the most efficient operation in terms of adding,
and sets allow the most efficient operation in terms of adding,
removing and updating elements.
</para>
<para>
There is, arguably, one more advantage that indexed collections have over sets for
many to many associations or collections of values. Because of the structure of a
<literal>Set</literal>, Hibernate doesn't ever <literal>UPDATE</literal> a row when
many-to-many associations or collections of values. Because of the structure of a
<literal>Set</literal>, Hibernate does not <literal>UPDATE</literal> a row when
an element is "changed". Changes to a <literal>Set</literal> always work via
<literal>INSERT</literal> and <literal>DELETE</literal> (of individual rows). Once
again, this consideration does not apply to one to many associations.
<literal>INSERT</literal> and <literal>DELETE</literal> of individual rows. Once
again, this consideration does not apply to one-to-many associations.
</para>
<para>
After observing that arrays cannot be lazy, we would conclude that lists, maps and
After observing that arrays cannot be lazy, you can conclude that lists, maps and
idbags are the most performant (non-inverse) collection types, with sets not far
behind. Sets are expected to be the most common kind of collection in Hibernate
behind. You can expect sets to be the most common kind of collection in Hibernate
applications. This is because the "set" semantics are most natural in the relational
model.
</para>
<para>
However, in well-designed Hibernate domain models, we usually see that most collections
However, in well-designed Hibernate domain models, most collections
are in fact one-to-many associations with <literal>inverse="true"</literal>. For these
associations, the update is handled by the many-to-one end of the association, and so
considerations of collection update performance simply do not apply.
@ -1216,13 +1221,13 @@ hibernate.cache.use_structured_entries true]]></programlisting>
<title>Bags and lists are the most efficient inverse collections</title>
<para>
Just before you ditch bags forever, there is a particular case in which bags (and also lists)
are much more performant than sets. For a collection with <literal>inverse="true"</literal>
(the standard bidirectional one-to-many relationship idiom, for example) we can add elements
to a bag or list without needing to initialize (fetch) the bag elements! This is because
There is a particular case, however, in which bags, and also lists,
are much more performant than sets. For a collection with <literal>inverse="true"</literal>,
the standard bidirectional one-to-many relationship idiom, for example, we can add elements
to a bag or list without needing to initialize (fetch) the bag elements. This is because, unlike a <literal>set</literal>,
<literal>Collection.add()</literal> or <literal>Collection.addAll()</literal> must always
return true for a bag or <literal>List</literal> (unlike a <literal>Set</literal>). This can
make the following common code much faster.
return true for a bag or <literal>List</literal>. This can
make the following common code much faster:
</para>
<programlisting><![CDATA[Parent p = (Parent) sess.load(Parent.class, id);
@ -1237,16 +1242,16 @@ sess.flush();]]></programlisting>
<title>One shot delete</title>
<para>
Occasionally, deleting collection elements one by one can be extremely inefficient. Hibernate
isn't completely stupid, so it knows not to do that in the case of an newly-empty collection
Deleting collection elements one by one can sometimes be extremely inefficient. Hibernate
knows not to do that in the case of an newly-empty collection
(if you called <literal>list.clear()</literal>, for example). In this case, Hibernate will
issue a single <literal>DELETE</literal> and we are done!
issue a single <literal>DELETE</literal>.
</para>
<para>
Suppose we add a single element to a collection of size twenty and then remove two elements.
Suppose you added a single element to a collection of size twenty and then remove two elements.
Hibernate will issue one <literal>INSERT</literal> statement and two <literal>DELETE</literal>
statements (unless the collection is a bag). This is certainly desirable.
statements, unless the collection is a bag. This is certainly desirable.
</para>
<para>
@ -1259,25 +1264,25 @@ sess.flush();]]></programlisting>
<para>delete eighteen rows one by one and then insert three rows</para>
</listitem>
<listitem>
<para>remove the whole collection (in one SQL <literal>DELETE</literal>) and insert
all five current elements (one by one)</para>
<para>remove the whole collection in one SQL <literal>DELETE</literal> and insert
all five current elements one by one</para>
</listitem>
</itemizedlist>
<para>
Hibernate isn't smart enough to know that the second option is probably quicker in this case.
(And it would probably be undesirable for Hibernate to be that smart; such behaviour might
confuse database triggers, etc.)
Hibernate cannot know that the second option is probably quicker.
It would probably be undesirable for Hibernate to be that intuitive as such behavior might
confuse database triggers, etc.
</para>
<para>
Fortunately, you can force this behaviour (ie. the second strategy) at any time by discarding
(ie. dereferencing) the original collection and returning a newly instantiated collection with
all the current elements. This can be very useful and powerful from time to time.
Fortunately, you can force this behavior (i.e. the second strategy) at any time by discarding
(i.e. dereferencing) the original collection and returning a newly instantiated collection with
all the current elements.
</para>
<para>
Of course, one-shot-delete does not apply to collections mapped <literal>inverse="true"</literal>.
One-shot-delete does not apply to collections mapped <literal>inverse="true"</literal>.
</para>
</sect2>
@ -1304,7 +1309,7 @@ sess.flush();]]></programlisting>
<para>
Hibernate can also use JMX to publish metrics if you enable the
<literal>StatisticsService</literal> MBean. You may enable a single MBean for all your
<literal>StatisticsService</literal> MBean. You can enable a single MBean for all your
<literal>SessionFactory</literal> or one per factory. See the following code for
minimalistic configuration examples:
</para>
@ -1329,13 +1334,13 @@ ObjectName on = new ObjectName("hibernate", tb); // MBean object name
StatisticsService stats = new StatisticsService(); // MBean implementation
server.registerMBean(stats, on); // Register the MBean on the server]]></programlisting>
<para>
TODO: This doesn't make sense: In the first case, we retrieve and use the MBean directly. In the second one, we must give
<!--<para>
TODO: This does not make sense: In the first case, we retrieve and use the MBean directly. In the second one, we must give
the JNDI name in which the session factory is held before using it. Use
<literal>hibernateStatsBean.setSessionFactoryJNDIName("my/JNDI/Name")</literal>
</para>
</para>-->
<para>
You can (de)activate the monitoring for a <literal>SessionFactory</literal>
You can activate and deactivate the monitoring for a <literal>SessionFactory</literal>:
</para>
<itemizedlist>
<listitem>
@ -1365,8 +1370,8 @@ server.registerMBean(stats, on); // Register the MBean on the server]]></program
<title>Metrics</title>
<para>
Hibernate provides a number of metrics, from very basic to the specialized information
only relevant in certain scenarios. All available counters are described in the
Hibernate provides a number of metrics, from basic information to more specialized information
that is only relevant in certain scenarios. All available counters are described in the
<literal>Statistics</literal> interface API, in three categories:
</para>
<itemizedlist>
@ -1378,8 +1383,8 @@ server.registerMBean(stats, on); // Register the MBean on the server]]></program
</listitem>
<listitem>
<para>
Metrics related to he entities, collections, queries, and caches as a
whole (aka global metrics),
Metrics related to the entities, collections, queries, and caches as a
whole (aka global metrics).
</para>
</listitem>
<listitem>
@ -1392,9 +1397,9 @@ server.registerMBean(stats, on); // Register the MBean on the server]]></program
<para>
For example, you can check the cache hit, miss, and put ratio of entities, collections
and queries, and the average time a query needs. Beware that the number of milliseconds
is subject to approximation in Java. Hibernate is tied to the JVM precision, on some
platforms this might even only be accurate to 10 seconds.
and queries, and the average time a query needs. Be aware that the number of milliseconds
is subject to approximation in Java. Hibernate is tied to the JVM precision and on some
platforms this might only be accurate to 10 seconds.
</para>
<para>
@ -1404,7 +1409,7 @@ server.registerMBean(stats, on); // Register the MBean on the server]]></program
refer to the <literal>Statistics</literal>, <literal>EntityStatistics</literal>,
<literal>CollectionStatistics</literal>, <literal>SecondLevelCacheStatistics</literal>,
and <literal>QueryStatistics</literal> API Javadoc for more information. The following
code shows a simple example:
code is a simple example:
</para>
<programlisting><![CDATA[Statistics stats = HibernateUtil.sessionFactory.getStatistics();
@ -1425,8 +1430,8 @@ long changes =
log.info(Cat.class.getName() + " changed " + changes + "times" );]]></programlisting>
<para>
To work on all entities, collections, queries and region caches, you can retrieve
the list of names of entities, collections, queries and region caches with the
You can work on all entities, collections, queries and region caches, by retrieving
the list of names of entities, collections, queries and region caches using the
following methods: <literal>getQueries()</literal>, <literal>getEntityNames()</literal>,
<literal>getCollectionRoleNames()</literal>, and
<literal>getSecondLevelCacheRegionNames()</literal>.

View File

@ -32,22 +32,22 @@
Persistent classes are classes in an application that implement the entities
of the business problem (e.g. Customer and Order in an E-commerce application).
Not all instances of a persistent class are considered to be in the persistent
state - an instance may instead be transient or detached.
state. For example, an instance can instead be transient or detached.
</para>
<para>
Hibernate works best if these classes follow some simple rules, also known
as the Plain Old Java Object (POJO) programming model. However, none of these
rules are hard requirements. Indeed, Hibernate3 assumes very little about
the nature of your persistent objects. You may express a domain model in other
ways: using trees of <literal>Map</literal> instances, for example.
the nature of your persistent objects. You can express a domain model in other
ways (using trees of <literal>Map</literal> instances, for example).
</para>
<sect1 id="persistent-classes-pojo">
<title>A simple POJO example</title>
<para>
Most Java applications require a persistent class representing felines.
Most Java applications require a persistent class representing felines. For example:
</para>
<programlisting><![CDATA[package eg;
@ -130,7 +130,7 @@ public class Cat {
}]]></programlisting>
<para>
There are four main rules to follow here:
The four main rules of persistent classes are explored in more detail in the following sections.
</para>
@ -139,8 +139,8 @@ public class Cat {
<para>
<literal>Cat</literal> has a no-argument constructor. All persistent classes must
have a default constructor (which may be non-public) so that Hibernate can instantiate
them using <literal>Constructor.newInstance()</literal>. We strongly recommend having a
have a default constructor (which can be non-public) so that Hibernate can instantiate
them using <literal>Constructor.newInstance()</literal>. It is recommended that you have a
default constructor with at least <emphasis>package</emphasis> visibility for runtime proxy
generation in Hibernate.
</para>
@ -153,9 +153,9 @@ public class Cat {
<literal>Cat</literal> has a property called <literal>id</literal>. This property
maps to the primary key column of a database table. The property might have been called
anything, and its type might have been any primitive type, any primitive "wrapper"
type, <literal>java.lang.String</literal> or <literal>java.util.Date</literal>. (If
your legacy database table has composite keys, you can even use a user-defined class
with properties of these types - see the section on composite identifiers later.)
type, <literal>java.lang.String</literal> or <literal>java.util.Date</literal>. If
your legacy database table has composite keys, you can use a user-defined class
with properties of these types (see the section on composite identifiers later in the chapter.)
</para>
<para>
@ -164,7 +164,7 @@ public class Cat {
</para>
<para>
In fact, some functionality is available only to classes which declare an
In fact, some functionality is available only to classes that declare an
identifier property:
</para>
@ -188,8 +188,8 @@ public class Cat {
</itemizedlist>
<para>
We recommend you declare consistently-named identifier properties on persistent
classes. We further recommend that you use a nullable (ie. non-primitive) type.
We recommend that you declare consistently-named identifier properties on persistent
classes and that you use a nullable (i.e., non-primitive) type.
</para>
</sect2>
@ -202,8 +202,8 @@ public class Cat {
</para>
<para>
You can persist <literal>final</literal> classes that do not implement an interface
with Hibernate, but you won't be able to use proxies for lazy association fetching -
which will limit your options for performance tuning.
with Hibernate. You will not, however, be able to use proxies for lazy association fetching which
will ultimately limit your options for performance tuning.
</para>
<para>
You should also avoid declaring <literal>public final</literal> methods on the
@ -217,12 +217,12 @@ public class Cat {
<para>
<literal>Cat</literal> declares accessor methods for all its persistent fields.
Many other ORM tools directly persist instance variables. We believe it is
Many other ORM tools directly persist instance variables. It is
better to provide an indirection between the relational schema and internal
data structures of the class. By default, Hibernate persists JavaBeans style
properties, and recognizes method names of the form <literal>getFoo</literal>,
<literal>isFoo</literal> and <literal>setFoo</literal>. You may switch to direct
field access for particular properties, if needed.
properties and recognizes method names of the form <literal>getFoo</literal>,
<literal>isFoo</literal> and <literal>setFoo</literal>. If required, you can switch to direct
field access for particular properties.
</para>
<para>
@ -240,7 +240,7 @@ public class Cat {
<para>
A subclass must also observe the first and second rules. It inherits its
identifier property from the superclass, <literal>Cat</literal>.
identifier property from the superclass, <literal>Cat</literal>. For example:
</para>
<programlisting><![CDATA[package eg;
@ -262,13 +262,13 @@ public class DomesticCat extends Cat {
<para>
You have to override the <literal>equals()</literal> and <literal>hashCode()</literal>
methods if you
methods if you:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
intend to put instances of persistent classes in a <literal>Set</literal>
(the recommended way to represent many-valued associations)
(the recommended way to represent many-valued associations);
<emphasis>and</emphasis>
</para>
</listitem>
@ -281,31 +281,31 @@ public class DomesticCat extends Cat {
<para>
Hibernate guarantees equivalence of persistent identity (database row) and Java identity
only inside a particular session scope. So as soon as we mix instances retrieved in
different sessions, we must implement <literal>equals()</literal> and
<literal>hashCode()</literal> if we wish to have meaningful semantics for
only inside a particular session scope. When you mix instances retrieved in
different sessions, you must implement <literal>equals()</literal> and
<literal>hashCode()</literal> if you wish to have meaningful semantics for
<literal>Set</literal>s.
</para>
<para>
The most obvious way is to implement <literal>equals()</literal>/<literal>hashCode()</literal>
by comparing the identifier value of both objects. If the value is the same, both must
be the same database row, they are therefore equal (if both are added to a <literal>Set</literal>,
we will only have one element in the <literal>Set</literal>). Unfortunately, we can't use that
approach with generated identifiers! Hibernate will only assign identifier values to objects
that are persistent, a newly created instance will not have any identifier value! Furthermore,
be the same database row, because they are equal. If both are added to a <literal>Set</literal>,
you will only have one element in the <literal>Set</literal>). Unfortunately, you cannot use that
approach with generated identifiers. Hibernate will only assign identifier values to objects
that are persistent; a newly created instance will not have any identifier value. Furthermore,
if an instance is unsaved and currently in a <literal>Set</literal>, saving it will assign
an identifier value to the object. If <literal>equals()</literal> and <literal>hashCode()</literal>
are based on the identifier value, the hash code would change, breaking the contract of the
<literal>Set</literal>. See the Hibernate website for a full discussion of this problem. Note
that this is not a Hibernate issue, but normal Java semantics of object identity and equality.
<literal>Set</literal>. See the Hibernate website for a full discussion of this problem. This is not
a Hibernate issue, but normal Java semantics of object identity and equality.
</para>
<para>
We recommend implementing <literal>equals()</literal> and <literal>hashCode()</literal>
It is recommended that you implement <literal>equals()</literal> and <literal>hashCode()</literal>
using <emphasis>Business key equality</emphasis>. Business key equality means that the
<literal>equals()</literal> method compares only the properties that form the business
key, a key that would identify our instance in the real world (a
key. It is a key that would identify our instance in the real world (a
<emphasis>natural</emphasis> candidate key):
</para>
@ -334,7 +334,7 @@ public class DomesticCat extends Cat {
}]]></programlisting>
<para>
Note that a business key does not have to be as solid as a database
A business key does not have to be as solid as a database
primary key candidate (see <xref linkend="transactions-basics-identity"/>).
Immutable or unique properties are usually good
candidates for a business key.
@ -345,30 +345,33 @@ public class DomesticCat extends Cat {
<sect1 id="persistent-classes-dynamicmodels">
<title>Dynamic models</title>
<para>
<emphasis>Note that the following features are currently considered
<note><title>Note</title>
<para>
<emphasis>The following features are currently considered
experimental and may change in the near future.</emphasis>
</para>
</para>
</note>
<para>
Persistent entities don't necessarily have to be represented as POJO classes
Persistent entities do not necessarily have to be represented as POJO classes
or as JavaBean objects at runtime. Hibernate also supports dynamic models
(using <literal>Map</literal>s of <literal>Map</literal>s at runtime) and the
representation of entities as DOM4J trees. With this approach, you don't
representation of entities as DOM4J trees. With this approach, you do not
write persistent classes, only mapping files.
</para>
<para>
By default, Hibernate works in normal POJO mode. You may set a default entity
By default, Hibernate works in normal POJO mode. You can set a default entity
representation mode for a particular <literal>SessionFactory</literal> using the
<literal>default_entity_mode</literal> configuration option (see
<xref linkend="configuration-optional-properties"/>.
<xref linkend="configuration-optional-properties"/>).
</para>
<para>
The following examples demonstrates the representation using <literal>Map</literal>s.
First, in the mapping file, an <literal>entity-name</literal> has to be declared
instead of (or in addition to) a class name:
The following examples demonstrate the representation using <literal>Map</literal>s.
First, in the mapping file an <literal>entity-name</literal> has to be declared
instead of, or in addition to, a class name:
</para>
<programlisting><![CDATA[<hibernate-mapping>
@ -407,14 +410,14 @@ public class DomesticCat extends Cat {
<para>
Note that even though associations are declared using target class names,
the target type of an associations may also be a dynamic entity instead
Even though associations are declared using target class names,
the target type of associations can also be a dynamic entity instead
of a POJO.
</para>
<para>
After setting the default entity mode to <literal>dynamic-map</literal>
for the <literal>SessionFactory</literal>, we can at runtime work with
for the <literal>SessionFactory</literal>, you can, at runtime, work with
<literal>Map</literal>s of <literal>Map</literal>s:
</para>
@ -441,10 +444,10 @@ tx.commit();
s.close();]]></programlisting>
<para>
The advantages of a dynamic mapping are quick turnaround time for prototyping
One of the main advantages of dynamic mapping is quick turnaround time for prototyping,
without the need for entity class implementation. However, you lose compile-time
type checking and will very likely deal with many exceptions at runtime. Thanks
to the Hibernate mapping, the database schema can easily be normalized and sound,
type checking and will likely deal with many exceptions at runtime. As a result of
the Hibernate mapping, the database schema can easily be normalized and sound,
allowing to add a proper domain model implementation on top later on.
</para>
@ -472,7 +475,7 @@ dynamicSession.close()
<literal>EntityMode</literal> is on the <literal>Session</literal> API, not the
<literal>SessionFactory</literal>. That way, the new <literal>Session</literal>
shares the underlying JDBC connection, transaction, and other context
information. This means you don't have tocall <literal>flush()</literal>
information. This means you do not have to call <literal>flush()</literal>
and <literal>close()</literal> on the secondary <literal>Session</literal>, and
also leave the transaction and connection handling to the primary unit of work.
</para>
@ -489,13 +492,16 @@ dynamicSession.close()
<para>
<literal>org.hibernate.tuple.Tuplizer</literal>, and its sub-interfaces, are responsible
for managing a particular representation of a piece of data, given that representation's
for managing a particular representation of a piece of data given that representation's
<literal>org.hibernate.EntityMode</literal>. If a given piece of data is thought of as
a data structure, then a tuplizer is the thing which knows how to create such a data structure
a data structure, then a tuplizer is the thing that knows how to create such a data structure
and how to extract values from and inject values into such a data structure. For example,
for the POJO entity mode, the correpsonding tuplizer knows how create the POJO through its
constructor and how to access the POJO properties using the defined property accessors.
There are two high-level types of Tuplizers, represented by the
for the POJO entity mode, the corresponding tuplizer knows how create the POJO through its
constructor. It also knows how to access the POJO properties using the defined property accessors.
</para>
<para>
There are two high-level types of Tuplizers, represented by the
<literal>org.hibernate.tuple.entity.EntityTuplizer</literal> and <literal>org.hibernate.tuple.component.ComponentTuplizer</literal>
interfaces. <literal>EntityTuplizer</literal>s are responsible for managing the above mentioned
contracts in regards to entities, while <literal>ComponentTuplizer</literal>s do the same for
@ -503,11 +509,11 @@ dynamicSession.close()
</para>
<para>
Users may also plug in their own tuplizers. Perhaps you require that a <literal>java.util.Map</literal>
Users can also plug in their own tuplizers. Perhaps you require that a <literal>java.util.Map</literal>
implementation other than <literal>java.util.HashMap</literal> be used while in the
dynamic-map entity-mode; or perhaps you need to define a different proxy generation strategy
dynamic-map entity-mode. Or perhaps you need to define a different proxy generation strategy
than the one used by default. Both would be achieved by defining a custom tuplizer
implementation. Tuplizers definitions are attached to the entity or component mapping they
implementation. Tuplizer definitions are attached to the entity or component mapping they
are meant to manage. Going back to the example of our customer entity:
</para>
@ -545,17 +551,17 @@ public class CustomMapTuplizerImpl
return new CustomMap();
}
}
}]]></programlisting>
}]]></programlisting>m
</sect1>
<sect1 id="persistent-classes-extensions">
<title>Extentsions</title>
<!--<sect1 id="persistent-classes-extensions">
<title>Extensions</title>
<para>
TODO: Document user-extension framework in the property and proxy packages
</para>
</sect1>
</sect1>-->
</chapter>

View File

@ -39,12 +39,12 @@
<para>
Hibernate not only takes care of the mapping from Java classes to
database tables (and from Java data types to SQL data types), but also provides data
query and retrieval facilities and can significantly reduce development time otherwise
query and retrieval facilities. It can also significantly reduce development time otherwise
spent with manual data handling in SQL and JDBC.
</para>
<para>
Hibernates goal is to relieve the developer from 95 percent of common data persistence
Hibernate's goal is to relieve the developer from 95 percent of common data persistence
related programming tasks. Hibernate may not be the best solution for data-centric
applications that only use stored-procedures to implement the business logic in the
database, it is most useful with object-oriented domain models and business logic in
@ -75,8 +75,8 @@
</listitem>
<listitem>
<para>
Have a look at the <literal>eg/</literal> directory in the Hibernate
distribution, it contains a simple standalone application. Copy your
View the <literal>eg/</literal> directory in the Hibernate
distribution. It contains a simple standalone application. Copy your
JDBC driver to the <literal>lib/</literal> directory and edit
<literal>etc/hibernate.properties</literal>, specifying correct values for
your database. From a command prompt in the distribution directory,
@ -89,7 +89,7 @@
Use this reference documentation as your primary source of information.
Consider reading <emphasis>Java Persistence with Hibernate</emphasis>
(http://www.manning.com/bauer2) if you need more help with application
design or if you prefer a step-by-step tutorial. Also visit
design, or if you prefer a step-by-step tutorial. Also visit
http://caveatemptor.hibernate.org and download the example application
for Java Persistence with Hibernate.
</para>
@ -116,7 +116,7 @@
<para>
If you have questions, use the user forum linked on the Hibernate website. We also
provide a JIRA issue trackings system for bug reports and feature requests. If you
provide a JIRA issue tracking system for bug reports and feature requests. If you
are interested in the development of Hibernate, join the developer mailing list. If
you are interested in translating this documentation into your language, contact us
on the developer mailing list.

View File

@ -64,7 +64,7 @@ List cats = crit.list();]]></programlisting>
.list();]]></programlisting>
<para>
Restrictions may be grouped logically.
Restrictions can be grouped logically.
</para>
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
@ -86,8 +86,8 @@ List cats = crit.list();]]></programlisting>
.list();]]></programlisting>
<para>
There are quite a range of built-in criterion types (<literal>Restrictions</literal>
subclasses), but one that is especially useful lets you specify SQL directly.
There are a range of built-in criterion types (<literal>Restrictions</literal>
subclasses). One of the most useful allows you to specify SQL directly.
</para>
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
@ -100,9 +100,9 @@ List cats = crit.list();]]></programlisting>
</para>
<para>
An alternative approach to obtaining a criterion is to get it from a
You can also obtain a criterion from a
<literal>Property</literal> instance. You can create a <literal>Property</literal>
by calling <literal>Property.forName()</literal>.
by calling <literal>Property.forName()</literal>:
</para>
<programlisting><![CDATA[
@ -123,7 +123,7 @@ List cats = sess.createCriteria(Cat.class)
<title>Ordering the results</title>
<para>
You may order the results using <literal>org.hibernate.criterion.Order</literal>.
You can order the results using <literal>org.hibernate.criterion.Order</literal>.
</para>
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
@ -146,8 +146,8 @@ List cats = sess.createCriteria(Cat.class)
<title>Associations</title>
<para>
You may easily specify constraints upon related entities by navigating
associations using <literal>createCriteria()</literal>.
By navigating
associations using <literal>createCriteria()</literal> you can specify constraints upon related entities:
</para>
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
@ -157,13 +157,13 @@ List cats = sess.createCriteria(Cat.class)
.list();]]></programlisting>
<para>
note that the second <literal>createCriteria()</literal> returns a new
instance of <literal>Criteria</literal>, which refers to the elements of
The second <literal>createCriteria()</literal> returns a new
instance of <literal>Criteria</literal> that refers to the elements of
the <literal>kittens</literal> collection.
</para>
<para>
The following, alternate form is useful in certain circumstances.
There is also an alternate form that is useful in certain circumstances:
</para>
<programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
@ -178,9 +178,9 @@ List cats = sess.createCriteria(Cat.class)
</para>
<para>
Note that the kittens collections held by the <literal>Cat</literal> instances
The kittens collections held by the <literal>Cat</literal> instances
returned by the previous two queries are <emphasis>not</emphasis> pre-filtered
by the criteria! If you wish to retrieve just the kittens that match the
by the criteria. If you want to retrieve just the kittens that match the
criteria, you must use a <literal>ResultTransformer</literal>.
</para>
@ -202,7 +202,7 @@ while ( iter.hasNext() ) {
<title>Dynamic association fetching</title>
<para>
You may specify association fetching semantics at runtime using
You can specify association fetching semantics at runtime using
<literal>setFetchMode()</literal>.
</para>
@ -268,7 +268,7 @@ List results = session.createCriteria(Cat.class)
<title>Projections, aggregation and grouping</title>
<para>
The class <literal>org.hibernate.criterion.Projections</literal> is a
factory for <literal>Projection</literal> instances. We apply a
factory for <literal>Projection</literal> instances. You can apply a
projection to a query by calling <literal>setProjection()</literal>.
</para>
@ -293,8 +293,8 @@ List results = session.createCriteria(Cat.class)
</para>
<para>
An alias may optionally be assigned to a projection, so that the projected value
may be referred to in restrictions or orderings. Here are two different ways to
An alias can be assigned to a projection so that the projected value
can be referred to in restrictions or orderings. Here are two different ways to
do this:
</para>
@ -361,8 +361,8 @@ List results = session.createCriteria(Cat.class)
<sect1 id="querycriteria-detachedqueries">
<title>Detached queries and subqueries</title>
<para>
The <literal>DetachedCriteria</literal> class lets you create a query outside the scope
of a session, and then later execute it using some arbitrary <literal>Session</literal>.
The <literal>DetachedCriteria</literal> class allows you to create a query outside the scope
of a session and then execute it using an arbitrary <literal>Session</literal>.
</para>
<programlisting><![CDATA[DetachedCriteria query = DetachedCriteria.forClass(Cat.class)
@ -375,8 +375,8 @@ txn.commit();
session.close();]]></programlisting>
<para>
A <literal>DetachedCriteria</literal> may also be used to express a subquery. Criterion
instances involving subqueries may be obtained via <literal>Subqueries</literal> or
A <literal>DetachedCriteria</literal> can also be used to express a subquery. Criterion
instances involving subqueries can be obtained via <literal>Subqueries</literal> or
<literal>Property</literal>.
</para>
@ -393,7 +393,7 @@ session.createCriteria(Cat.class)
.list();]]></programlisting>
<para>
Even correlated subqueries are possible:
Correlated subqueries are also possible:
</para>
<programlisting><![CDATA[DetachedCriteria avgWeightForSex = DetachedCriteria.forClass(Cat.class, "cat2")
@ -413,16 +413,16 @@ session.createCriteria(Cat.class, "cat")
<title>Queries by natural identifier</title>
<para>
For most queries, including criteria queries, the query cache is not very efficient,
because query cache invalidation occurs too frequently. However, there is one special
kind of query where we can optimize the cache invalidation algorithm: lookups by a
For most queries, including criteria queries, the query cache is not efficient
because query cache invalidation occurs too frequently. However, there is a special
kind of query where you can optimize the cache invalidation algorithm: lookups by a
constant natural key. In some applications, this kind of query occurs frequently.
The criteria API provides special provision for this use case.
</para>
<para>
First, you should map the natural key of your entity using
<literal>&lt;natural-id&gt;</literal>, and enable use of the second-level cache.
First, map the natural key of your entity using
<literal>&lt;natural-id&gt;</literal> and enable use of the second-level cache.
</para>
<programlisting><![CDATA[<class name="User">
@ -438,16 +438,13 @@ session.createCriteria(Cat.class, "cat")
</class>]]></programlisting>
<para>
Note that this functionality is not intended for use with entities with
This functionality is not intended for use with entities with
<emphasis>mutable</emphasis> natural keys.
</para>
<para>
Next, enable the Hibernate query cache.
</para>
<para>
Now, <literal>Restrictions.naturalId()</literal> allows us to make use of
Once you have enabled the Hibernate query cache,
the <literal>Restrictions.naturalId()</literal> allows you to make use of
the more efficient cache algorithm.
</para>

View File

@ -29,28 +29,28 @@
<title>HQL: The Hibernate Query Language</title>
<para>
Hibernate is equipped with an extremely powerful query language that (quite intentionally)
looks very much like SQL. But don't be fooled by the syntax; HQL is fully object-oriented,
understanding notions like inheritence, polymorphism and association.
Hibernate uses a powerful query language (HQL) that is similar in appearance to
SQL. Compared with SQL, however, HQL is fully object-oriented
and understands notions like inheritance, polymorphism and association.
</para>
<sect1 id="queryhql-casesensitivity">
<title>Case Sensitivity</title>
<para>
Queries are case-insensitive, except for names of Java classes and properties.
With the exception of names of Java classes and properties, queries are case-insensitive.
So <literal>SeLeCT</literal> is the same as
<literal>sELEct</literal> is the same as
<literal>SELECT</literal> but
<literal>SELECT</literal>, but
<literal>org.hibernate.eg.FOO</literal> is not
<literal>org.hibernate.eg.Foo</literal> and
<literal>org.hibernate.eg.Foo</literal>, and
<literal>foo.barSet</literal> is not
<literal>foo.BARSET</literal>.
</para>
<para>
This manual uses lowercase HQL keywords. Some users find queries with uppercase keywords
more readable, but we find this convention ugly when embedded in Java code.
more readable, but this convention is unsuitable for queries embedded in Java code.
</para>
</sect1>
@ -65,40 +65,40 @@
<programlisting><![CDATA[from eg.Cat]]></programlisting>
<para>
which simply returns all instances of the class <literal>eg.Cat</literal>.
We don't usually need to qualify the class name, since <literal>auto-import</literal>
is the default. So we almost always just write:
This returns all instances of the class <literal>eg.Cat</literal>.
You do not usually need to qualify the class name, since <literal>auto-import</literal>
is the default. For example:
</para>
<programlisting><![CDATA[from Cat]]></programlisting>
<para>
Most of the time, you will need to assign an <emphasis>alias</emphasis>, since
you will want to refer to the <literal>Cat</literal> in other parts of the
query.
In order to refer to the <literal>Cat</literal> in other parts of the
query, you will need to assign an <emphasis>alias</emphasis>. For example:
</para>
<programlisting><![CDATA[from Cat as cat]]></programlisting>
<para>
This query assigns the alias <literal>cat</literal> to <literal>Cat</literal>
instances, so we could use that alias later in the query. The <literal>as</literal>
keyword is optional; we could also write:
instances, so you can use that alias later in the query. The <literal>as</literal>
keyword is optional. You could also write:
</para>
<programlisting><![CDATA[from Cat cat]]></programlisting>
<para>
Multiple classes may appear, resulting in a cartesian product or "cross" join.
Multiple classes can appear, resulting in a cartesian product or "cross" join.
</para>
<programlisting><![CDATA[from Formula, Parameter]]></programlisting>
<programlisting><![CDATA[from Formula as form, Parameter as param]]></programlisting>
<para>
It is considered good practice to name query aliases using an initial lowercase,
It is good practice to name query aliases using an initial lowercase as this is
consistent with Java naming standards for local variables
(eg. <literal>domesticCat</literal>).
(e.g. <literal>domesticCat</literal>).
</para>
</sect1>
@ -107,8 +107,8 @@
<title>Associations and joins</title>
<para>
We may also assign aliases to associated entities, or even to elements of a
collection of values, using a <literal>join</literal>.
You can also assign aliases to associated entities or to elements of a
collection of values using a <literal>join</literal>. For example:
</para>
<programlisting><![CDATA[from Cat as cat
@ -120,7 +120,7 @@
<programlisting><![CDATA[from Formula form full join form.parameter param]]></programlisting>
<para>
The supported join types are borrowed from ANSI SQL
The supported join types are borrowed from ANSI SQL:
</para>
<itemizedlist spacing="compact">
@ -165,8 +165,8 @@
with kitten.bodyWeight > 10.0]]></programlisting>
<para>
In addition, a "fetch" join allows associations or collections of values to be
initialized along with their parent objects, using a single select. This is particularly
A "fetch" join allows associations or collections of values to be
initialized along with their parent objects using a single select. This is particularly
useful in the case of a collection. It effectively overrides the outer join and
lazy declarations of the mapping file for associations and collections. See
<xref linkend="performance-fetching"/> for more information.
@ -178,9 +178,9 @@
<para>
A fetch join does not usually need to assign an alias, because the associated objects
should not be used in the <literal>where</literal> clause (or any other clause). Also,
the associated objects are not returned directly in the query results. Instead, they may
be accessed via the parent object. The only reason we might need an alias is if we are
should not be used in the <literal>where</literal> clause (or any other clause).
The associated objects are also not returned directly in the query results. Instead, they may
be accessed via the parent object. The only reason you might need an alias is if you are
recursively join fetching a further collection:
</para>
@ -190,24 +190,24 @@
left join fetch child.kittens]]></programlisting>
<para>
Note that the <literal>fetch</literal> construct may not be used in queries called using
<literal>iterate()</literal> (though <literal>scroll()</literal> can be used). Nor should
<literal>fetch</literal> be used together with <literal>setMaxResults()</literal> or
<literal>setFirstResult()</literal> as these operations are based on the result rows, which
The <literal>fetch</literal> construct cannot be used in queries called using
<literal>iterate()</literal> (though <literal>scroll()</literal> can be used).
<literal>Fetch</literal> should be used together with <literal>setMaxResults()</literal> or
<literal>setFirstResult()</literal>, as these operations are based on the result rows which
usually contain duplicates for eager collection fetching, hence, the number of rows is not what
you'd expect.
Nor may <literal>fetch</literal> be used together with an ad hoc <literal>with</literal> condition.
you would expect.
<literal>Fetch</literal> should also not be used together with impromptu <literal>with</literal> condition.
It is possible to create a cartesian product by join fetching more than one collection in a
query, so take care in this case. Join fetching multiple collection roles also sometimes gives
unexpected results for bag mappings, so be careful about how you formulate your queries in this
query, so take care in this case. Join fetching multiple collection roles can produce
unexpected results for bag mappings, so user discretion is advised when formulating queries in this
case. Finally, note that <literal>full join fetch</literal> and <literal>right join fetch</literal>
are not meaningful.
</para>
<para>
If you are using property-level lazy fetching (with bytecode instrumentation), it is
possible to force Hibernate to fetch the lazy properties immediately (in the first
query) using <literal>fetch all properties</literal>.
possible to force Hibernate to fetch the lazy properties in the first query immediately
using <literal>fetch all properties</literal>.
</para>
<programlisting><![CDATA[from Document fetch all properties order by name]]></programlisting>
@ -223,7 +223,7 @@
</para>
<para>
The queries shown in the previous section all use the <literal>explicit</literal> form where
The queries shown in the previous section all use the <literal>explicit</literal> form, that is, where
the join keyword is explicitly used in the from clause. This is the recommended form.
</para>
@ -238,47 +238,50 @@
</sect1>
<sect1 id="queryhql-identifier-property">
<title>Refering to identifier property</title>
<title>Referring to identifier property</title>
<para>
There are, generally speaking, 2 ways to refer to an entity's identifier property:
There are 2 ways to refer to an entity's identifier property:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
The special property (lowercase) <literal>id</literal> may be used to reference the identifier
property of an entity <emphasis>provided that entity does not define a non-identifier property
property of an entity <emphasis>provided that the entity does not define a non-identifier property
named id</emphasis>.
</para>
</listitem>
<listitem>
<para>
If the entity defines a named identifier property, you may use that property name.
If the entity defines a named identifier property, you can use that property name.
</para>
</listitem>
</itemizedlist>
<para>
References to composite identifier properties follow the same naming rules. If the
References to composite identifier properties follow the same naming rules. If the
entity has a non-identifier property named id, the composite identifier property can only
be referenced by its defined named; otherwise, the special <literal>id</literal> property
can be used to rerference the identifier property.
be referenced by its defined named. Otherwise, the special <literal>id</literal> property
can be used to reference the identifier property.
</para>
<important>
<para>
Note: this has changed significantly starting in version 3.2.2. In previous versions,
<literal>id</literal> <emphasis>always</emphasis> referred to the identifier property no
matter what its actual name. A ramification of that decision was that non-identifier
Please note that, starting in version 3.2.2, this has changed significantly. In previous versions,
<literal>id</literal> <emphasis>always</emphasis> referred to the identifier property
regardless of its actual name. A ramification of that decision was that non-identifier
properties named <literal>id</literal> could never be referenced in Hibernate queries.
</para>
</sect1>
</important>
</sect1>
<sect1 id="queryhql-select">
<title>The select clause</title>
<para>
The <literal>select</literal> clause picks which objects and properties to return in
the query result set. Consider:
the query result set. Consider the following:
</para>
<programlisting><![CDATA[select mate
@ -287,13 +290,13 @@ from Cat as cat
<para>
The query will select <literal>mate</literal>s of other <literal>Cat</literal>s.
Actually, you may express this query more compactly as:
You can express this query more compactly as:
</para>
<programlisting><![CDATA[select cat.mate from Cat cat]]></programlisting>
<para>
Queries may return properties of any value type including properties of component type:
Queries can return properties of any value type including properties of component type:
</para>
<programlisting><![CDATA[select cat.name from DomesticCat cat
@ -302,8 +305,8 @@ where cat.name like 'fri%']]></programlisting>
<programlisting><![CDATA[select cust.name.firstName from Customer as cust]]></programlisting>
<para>
Queries may return multiple objects and/or properties as an array of type
<literal>Object[]</literal>,
Queries can return multiple objects and/or properties as an array of type
<literal>Object[]</literal>:
</para>
<programlisting><![CDATA[select mother, offspr, mate.name
@ -312,7 +315,7 @@ from DomesticCat as mother
left outer join mother.kittens as offspr]]></programlisting>
<para>
or as a <literal>List</literal>,
Or as a <literal>List</literal>:
</para>
<programlisting><![CDATA[select new list(mother, offspr, mate.name)
@ -321,7 +324,7 @@ from DomesticCat as mother
left outer join mother.kittens as offspr]]></programlisting>
<para>
or as an actual typesafe Java object,
Or - assuming that the class <literal>Family</literal> has an appropriate constructor - as an actual typesafe Java object:
</para>
<programlisting><![CDATA[select new Family(mother, mate, offspr)
@ -329,12 +332,9 @@ from DomesticCat as mother
join mother.mate as mate
left join mother.kittens as offspr]]></programlisting>
<para>
assuming that the class <literal>Family</literal> has an appropriate constructor.
</para>
<para>
You may assign aliases to selected expressions using <literal>as</literal>:
You can assign aliases to selected expressions using <literal>as</literal>:
</para>
<programlisting><![CDATA[select max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n
@ -357,7 +357,7 @@ from Cat cat]]></programlisting>
<title>Aggregate functions</title>
<para>
HQL queries may even return the results of aggregate functions on properties:
HQL queries can even return the results of aggregate functions on properties:
</para>
<programlisting><![CDATA[select avg(cat.weight), sum(cat.weight), max(cat.weight), count(cat)
@ -365,7 +365,7 @@ from Cat cat]]></programlisting>
<!-- NO LONGER SUPPORTED
<para>
Collections may also appear inside aggregate functions in the <literal>select</literal>
Collections can also appear inside aggregate functions in the <literal>select</literal>
clause.
</para>
@ -374,7 +374,7 @@ from Cat cat group by cat]]></programlisting>
-->
<para>
The supported aggregate functions are
The supported aggregate functions are:
</para>
<itemizedlist spacing="compact">
@ -396,7 +396,7 @@ from Cat cat group by cat]]></programlisting>
</itemizedlist>
<para>
You may use arithmetic operators, concatenation, and recognized SQL functions
You can use arithmetic operators, concatenation, and recognized SQL functions
in the select clause:
</para>
@ -408,7 +408,7 @@ group by cat.id, cat.weight]]></programlisting>
<programlisting><![CDATA[select firstName||' '||initial||' '||upper(lastName) from Person]]></programlisting>
<para>
The <literal>distinct</literal> and <literal>all</literal> keywords may be used and
The <literal>distinct</literal> and <literal>all</literal> keywords can be used and
have the same semantics as in SQL.
</para>
@ -429,7 +429,7 @@ select count(distinct cat.name), count(cat) from Cat cat]]></programlisting>
<para>
returns instances not only of <literal>Cat</literal>, but also of subclasses like
<literal>DomesticCat</literal>. Hibernate queries may name <emphasis>any</emphasis> Java
<literal>DomesticCat</literal>. Hibernate queries can name <emphasis>any</emphasis> Java
class or interface in the <literal>from</literal> clause. The query will return instances
of all persistent classes that extend that class or implement the interface. The following
query would return all persistent objects:
@ -445,9 +445,9 @@ select count(distinct cat.name), count(cat) from Cat cat]]></programlisting>
<programlisting><![CDATA[from Named n, Named m where n.name = m.name]]></programlisting>
<para>
Note that these last two queries will require more than one SQL <literal>SELECT</literal>. This
These last two queries will require more than one SQL <literal>SELECT</literal>. This
means that the <literal>order by</literal> clause does not correctly order the whole result set.
(It also means you can't call these queries using <literal>Query.scroll()</literal>.)
It also means you cannot call these queries using <literal>Query.scroll()</literal>.
</para>
</sect1>
@ -456,8 +456,8 @@ select count(distinct cat.name), count(cat) from Cat cat]]></programlisting>
<title>The where clause</title>
<para>
The <literal>where</literal> clause allows you to narrow the list of instances returned.
If no alias exists, you may refer to properties by name:
The <literal>where</literal> clause allows you to refine the list of instances returned.
If no alias exists, you can refer to properties by name:
</para>
<programlisting><![CDATA[from Cat where name='Fritz']]></programlisting>
@ -469,38 +469,40 @@ select count(distinct cat.name), count(cat) from Cat cat]]></programlisting>
<programlisting><![CDATA[from Cat as cat where cat.name='Fritz']]></programlisting>
<para>
returns instances of <literal>Cat</literal> named 'Fritz'.
This returns instances of <literal>Cat</literal> named 'Fritz'.
</para>
<para>
The following query:
<programlisting><![CDATA[select foo
from Foo foo, Bar bar
where foo.startDate = bar.date]]></programlisting>
<para>
will return all instances of <literal>Foo</literal> for which
there exists an instance of <literal>bar</literal> with a
returns all instances of <literal>Foo</literal> with an
instance of <literal>bar</literal> with a
<literal>date</literal> property equal to the
<literal>startDate</literal> property of the
<literal>Foo</literal>. Compound path expressions make the
<literal>where</literal> clause extremely powerful. Consider:
<literal>where</literal> clause extremely powerful. Consider the following:
</para>
<programlisting><![CDATA[from Cat cat where cat.mate.name is not null]]></programlisting>
<para>
This query translates to an SQL query with a table (inner) join. If you were to write
something like
This query translates to an SQL query with a table (inner) join. For example:
</para>
<programlisting><![CDATA[from Foo foo
where foo.bar.baz.customer.address.city is not null]]></programlisting>
<para>
you would end up with a query that would require four table joins in SQL.
would result in a query that would require four table joins in SQL.
</para>
<para>
The <literal>=</literal> operator may be used to compare not only properties, but also
The <literal>=</literal> operator can be used to compare not only properties, but also
instances:
</para>
@ -511,7 +513,7 @@ from Cat cat, Cat mate
where cat.mate = mate]]></programlisting>
<para>
The special property (lowercase) <literal>id</literal> may be used to reference the
The special property (lowercase) <literal>id</literal> can be used to reference the
unique identifier of an object. See <xref linkend="queryhql-identifier-property"/>
for more information.
</para>
@ -521,14 +523,13 @@ where cat.mate = mate]]></programlisting>
from Cat as cat where cat.mate.id = 69]]></programlisting>
<para>
The second query is efficient. No table join is required!
The second query is efficient and does not require a table join.
</para>
<para>
Properties of composite identifiers may also be used. Suppose <literal>Person</literal>
has a composite identifier consisting of <literal>country</literal> and
<literal>medicareNumber</literal>. Again, see <xref linkend="queryhql-identifier-property"/>
for more information regarding referencing identifier properties.
Properties of composite identifiers can also be used. Consider the following example where <literal>Person</literal>
has composite identifiers consisting of <literal>country</literal> and
<literal>medicareNumber</literal>:
</para>
<programlisting><![CDATA[from bank.Person person
@ -540,11 +541,16 @@ where account.owner.id.country = 'AU'
and account.owner.id.medicareNumber = 123456]]></programlisting>
<para>
Once again, the second query requires no table join.
Once again, the second query does not require a table join.
</para>
<para>
Likewise, the special property <literal>class</literal> accesses the discriminator value
<para>
See <xref linkend="queryhql-identifier-property"/>
for more information regarding referencing identifier properties)
</para>
<para>
The special property <literal>class</literal> accesses the discriminator value
of an instance in the case of polymorphic persistence. A Java class name embedded in the
where clause will be translated to its discriminator value.
</para>
@ -552,21 +558,21 @@ where account.owner.id.country = 'AU'
<programlisting><![CDATA[from Cat cat where cat.class = DomesticCat]]></programlisting>
<para>
You may also use components or composite user types, or properties of said
component types. See <xref linkend="queryhql-components"/> for more details.
You can also use components or composite user types, or properties of said
component types. See <xref linkend="queryhql-components"/> for more information.
</para>
<para>
An "any" type has the special properties <literal>id</literal> and <literal>class</literal>,
allowing us to express a join in the following way (where <literal>AuditLog.item</literal>
is a property mapped with <literal>&lt;any&gt;</literal>).
An "any" type has the special properties <literal>id</literal> and <literal>class</literal> that allows you
to express a join in the following way (where <literal>AuditLog.item</literal>
is a property mapped with <literal>&lt;any&gt;</literal>):
</para>
<programlisting><![CDATA[from AuditLog log, Payment payment
where log.item.class = 'Payment' and log.item.id = payment.id]]></programlisting>
<para>
Notice that <literal>log.item.class</literal> and <literal>payment.class</literal>
The <literal>log.item.class</literal> and <literal>payment.class</literal>
would refer to the values of completely different database columns in the above query.
</para>
@ -576,19 +582,19 @@ where log.item.class = 'Payment' and log.item.id = payment.id]]></programlisting
<title>Expressions</title>
<para>
Expressions allowed in the <literal>where</literal> clause include
most of the kind of things you could write in SQL:
Expressions used in the <literal>where</literal> clause include the following:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
mathematical operators <literal>+, -, *, /</literal>
mathematical operators: <literal>+, -, *, /</literal>
</para>
</listitem>
<listitem>
<para>
binary comparison operators <literal>=, &gt;=, &lt;=, &lt;&gt;, !=, like</literal>
binary comparison operators: <literal>=, &gt;=, &lt;=, &lt;&gt;, !=, like</literal>
</para>
</listitem>
<listitem>
@ -598,7 +604,7 @@ where log.item.class = 'Payment' and log.item.id = payment.id]]></programlisting
</listitem>
<listitem>
<para>
Parentheses <literal>( )</literal>, indicating grouping
Parentheses <literal>( )</literal> that indicates grouping
</para>
</listitem>
<listitem>
@ -627,7 +633,7 @@ where log.item.class = 'Payment' and log.item.id = payment.id]]></programlisting
</listitem>
<listitem>
<para>
<literal>current_date()</literal>, <literal>current_time()</literal>,
<literal>current_date()</literal>, <literal>current_time()</literal>, and
<literal>current_timestamp()</literal>
</para>
</listitem>
@ -635,7 +641,7 @@ where log.item.class = 'Payment' and log.item.id = payment.id]]></programlisting
<para>
<literal>second(...)</literal>, <literal>minute(...)</literal>,
<literal>hour(...)</literal>, <literal>day(...)</literal>,
<literal>month(...)</literal>, <literal>year(...)</literal>,
<literal>month(...)</literal>, and <literal>year(...)</literal>
</para>
</listitem>
<listitem>
@ -674,13 +680,13 @@ where log.item.class = 'Payment' and log.item.id = payment.id]]></programlisting
HQL functions that take collection-valued path expressions: <literal>size(),
minelement(), maxelement(), minindex(), maxindex()</literal>, along with the
special <literal>elements()</literal> and <literal>indices</literal> functions
which may be quantified using <literal>some, all, exists, any, in</literal>.
that can be quantified using <literal>some, all, exists, any, in</literal>.
</para>
</listitem>
<listitem>
<para>
Any database-supported SQL scalar function like <literal>sign()</literal>,
<literal>trunc()</literal>, <literal>rtrim()</literal>, <literal>sin()</literal>
<literal>trunc()</literal>, <literal>rtrim()</literal>, and <literal>sin()</literal>
</para>
</listitem>
<listitem>
@ -690,7 +696,7 @@ where log.item.class = 'Payment' and log.item.id = payment.id]]></programlisting
</listitem>
<listitem>
<para>
named parameters <literal>:name</literal>, <literal>:start_date</literal>, <literal>:x1</literal>
named parameters <literal>:name</literal>, <literal>:start_date</literal>, and <literal>:x1</literal>
</para>
</listitem>
<listitem>
@ -707,7 +713,7 @@ where log.item.class = 'Payment' and log.item.id = payment.id]]></programlisting
</itemizedlist>
<para>
<literal>in</literal> and <literal>between</literal> may be used as follows:
<literal>in</literal> and <literal>between</literal> can be used as follows:
</para>
<programlisting><![CDATA[from DomesticCat cat where cat.name between 'A' and 'B']]></programlisting>
@ -715,7 +721,7 @@ where log.item.class = 'Payment' and log.item.id = payment.id]]></programlisting
<programlisting><![CDATA[from DomesticCat cat where cat.name in ( 'Foo', 'Bar', 'Baz' )]]></programlisting>
<para>
and the negated forms may be written
The negated forms can be written as follows:
</para>
<programlisting><![CDATA[from DomesticCat cat where cat.name not between 'A' and 'B']]></programlisting>
@ -723,12 +729,12 @@ where log.item.class = 'Payment' and log.item.id = payment.id]]></programlisting
<programlisting><![CDATA[from DomesticCat cat where cat.name not in ( 'Foo', 'Bar', 'Baz' )]]></programlisting>
<para>
Likewise, <literal>is null</literal> and <literal>is not null</literal> may be used to test
Similarly, <literal>is null</literal> and <literal>is not null</literal> can be used to test
for null values.
</para>
<para>
Booleans may be easily used in expressions by declaring HQL query substitutions in Hibernate
Booleans can be easily used in expressions by declaring HQL query substitutions in Hibernate
configuration:
</para>
@ -742,7 +748,7 @@ where log.item.class = 'Payment' and log.item.id = payment.id]]></programlisting
<programlisting><![CDATA[from Cat cat where cat.alive = true]]></programlisting>
<para>
You may test the size of a collection with the special property <literal>size</literal>, or
You can test the size of a collection with the special property <literal>size</literal> or
the special <literal>size()</literal> function.
</para>
@ -751,11 +757,11 @@ where log.item.class = 'Payment' and log.item.id = payment.id]]></programlisting
<programlisting><![CDATA[from Cat cat where size(cat.kittens) > 0]]></programlisting>
<para>
For indexed collections, you may refer to the minimum and maximum indices using
For indexed collections, you can refer to the minimum and maximum indices using
<literal>minindex</literal> and <literal>maxindex</literal> functions. Similarly,
you may refer to the minimum and maximum elements of a collection of basic type
you can refer to the minimum and maximum elements of a collection of basic type
using the <literal>minelement</literal> and <literal>maxelement</literal>
functions.
functions. For example:
</para>
<programlisting><![CDATA[from Calendar cal where maxelement(cal.holidays) > current_date]]></programlisting>
@ -767,7 +773,7 @@ where log.item.class = 'Payment' and log.item.id = payment.id]]></programlisting
<para>
The SQL functions <literal>any, some, all, exists, in</literal> are supported when passed the element
or index set of a collection (<literal>elements</literal> and <literal>indices</literal> functions)
or the result of a subquery (see below).
or the result of a subquery (see below):
</para>
<programlisting><![CDATA[select mother from Cat as mother, Cat as kit
@ -785,13 +791,13 @@ where p.name = some elements(list.names)]]></programlisting>
<para>
Note that these constructs - <literal>size</literal>, <literal>elements</literal>,
<literal>indices</literal>, <literal>minindex</literal>, <literal>maxindex</literal>,
<literal>minelement</literal>, <literal>maxelement</literal> - may only be used in
<literal>minelement</literal>, <literal>maxelement</literal> - can only be used in
the where clause in Hibernate3.
</para>
<para>
Elements of indexed collections (arrays, lists, maps) may be referred to by
index (in a where clause only):
Elements of indexed collections (arrays, lists, and maps) can be referred to by
index in a where clause only:
</para>
<programlisting><![CDATA[from Order order where order.items[0].id = 1234]]></programlisting>
@ -807,14 +813,14 @@ where order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11]]></
where order.items[ maxindex(order.items) ] = item and order.id = 11]]></programlisting>
<para>
The expression inside <literal>[]</literal> may even be an arithmetic expression.
The expression inside <literal>[]</literal> can even be an arithmetic expression:
</para>
<programlisting><![CDATA[select item from Item item, Order order
where order.items[ size(order.items) - 1 ] = item]]></programlisting>
<para>
HQL also provides the built-in <literal>index()</literal> function, for elements
HQL also provides the built-in <literal>index()</literal> function for elements
of a one-to-many association or collection of values.
</para>
@ -823,13 +829,13 @@ where order.items[ size(order.items) - 1 ] = item]]></programlisting>
where index(item) < 5]]></programlisting>
<para>
Scalar SQL functions supported by the underlying database may be used
Scalar SQL functions supported by the underlying database can be used:
</para>
<programlisting><![CDATA[from DomesticCat cat where upper(cat.name) like 'FRI%']]></programlisting>
<para>
If you are not yet convinced by all this, think how much longer and less readable the
Consider how much longer and less readable the
following query would be in SQL:
</para>
@ -869,7 +875,7 @@ WHERE prod.name = 'widget'
<title>The order by clause</title>
<para>
The list returned by a query may be ordered by any property of a returned class or components:
The list returned by a query can be ordered by any property of a returned class or components:
</para>
<programlisting><![CDATA[from DomesticCat cat
@ -885,7 +891,7 @@ order by cat.name asc, cat.weight desc, cat.birthdate]]></programlisting>
<title>The group by clause</title>
<para>
A query that returns aggregate values may be grouped by any property of a returned class or components:
A query that returns aggregate values can be grouped by any property of a returned class or components:
</para>
<programlisting><![CDATA[select cat.color, sum(cat.weight), count(cat)
@ -907,8 +913,8 @@ having cat.color in (eg.Color.TABBY, eg.Color.BLACK)]]></programlisting>
<para>
SQL functions and aggregate functions are allowed in the <literal>having</literal>
and <literal>order by</literal> clauses, if supported by the underlying database
(eg. not in MySQL).
and <literal>order by</literal> clauses if they are supported by the underlying database
(i.e., not in MySQL).
</para>
<programlisting><![CDATA[select cat
@ -919,10 +925,10 @@ having avg(kitten.weight) > 100
order by count(kitten) asc, sum(kitten.weight) desc]]></programlisting>
<para>
Note that neither the <literal>group by</literal> clause nor the
<literal>order by</literal> clause may contain arithmetic expressions.
Also note that Hibernate currently does not expand a grouped entity,
so you can't write <literal>group by cat</literal> if all properties
Neither the <literal>group by</literal> clause nor the
<literal>order by</literal> clause can contain arithmetic expressions.
Hibernate also does not currently expand a grouped entity,
so you cannot write <literal>group by cat</literal> if all properties
of <literal>cat</literal> are non-aggregated. You have to list all
non-aggregated properties explicitly.
</para>
@ -962,12 +968,12 @@ where cat.name not in (
from Cat as cat]]></programlisting>
<para>
Note that HQL subqueries may occur only in the select or where clauses.
Note that HQL subqueries can occur only in the select or where clauses.
</para>
<para>
Note that subqueries can also utilize <literal>row value constructor</literal> syntax. See
<xref linkend="queryhql-tuple"/> for more details.
<xref linkend="queryhql-tuple"/> for more information.
</para>
</sect1>
@ -977,13 +983,13 @@ from Cat as cat]]></programlisting>
<para>
Hibernate queries can be quite powerful and complex. In fact, the power of the query language
is one of Hibernate's main selling points. Here are some example queries very similar to queries
that I used on a recent project. Note that most queries you will write are much simpler than these!
is one of Hibernate's main strengths. The following example queries are similar to queries
that have been used on recent projects. Please note that most queries you will write will be much simpler than the following examples.
</para>
<para>
The following query returns the order id, number of items and total value of the order for all
unpaid orders for a particular customer and given minimum total value, ordering the results by
The following query returns the order id, number of items, the given minimum total value and the total value of the order for all
unpaid orders for a particular customer. The results are ordered by
total value. In determining the prices, it uses the current catalog. The resulting SQL query,
against the <literal>ORDER</literal>, <literal>ORDER_LINE</literal>, <literal>PRODUCT</literal>,
<literal>CATALOG</literal> and <literal>PRICE</literal> tables has four inner joins and an
@ -1053,7 +1059,7 @@ group by status.name, status.sortOrder
order by status.sortOrder]]></programlisting>
<para>
If I would have mapped the <literal>statusChanges</literal> collection as a list, instead of a set,
If the <literal>statusChanges</literal> collection was mapped as a list, instead of a set,
the query would have been much simpler to write.
</para>
@ -1101,7 +1107,7 @@ order by account.type.sortOrder, account.accountNumber, payment.dueDate]]></prog
<para>
HQL now supports <literal>update</literal>, <literal>delete</literal> and
<literal>insert ... select ...</literal> statements.
See <xref linkend="batch-direct"/> for details.
See <xref linkend="batch-direct"/> for more information.
</para>
</sect1>
@ -1109,7 +1115,7 @@ order by account.type.sortOrder, account.accountNumber, payment.dueDate]]></prog
<title>Tips &amp; Tricks</title>
<para>
You can count the number of query results without actually returning them:
You can count the number of query results without returning them:
</para>
<programlisting><![CDATA[( (Integer) session.createQuery("select count(*) from ....").iterate().next() ).intValue()]]></programlisting>
@ -1132,7 +1138,7 @@ order by count(msg)]]></programlisting>
<programlisting><![CDATA[from User usr where size(usr.messages) >= 1]]></programlisting>
<para>
If your database doesn't support subselects, use the following query:
If your database does not support subselects, use the following query:
</para>
<programlisting><![CDATA[select usr.id, usr.name
@ -1141,8 +1147,9 @@ from User usr.name
group by usr.id, usr.name
having count(msg) >= 1]]></programlisting>
<para>
As this solution can't return a <literal>User</literal> with zero messages
As this solution cannot return a <literal>User</literal> with zero messages
because of the inner join, the following form is also useful:
</para>
@ -1170,7 +1177,7 @@ q.setFirstResult(PAGE_SIZE * pageNumber);
List page = q.list();]]></programlisting>
<para>
Collection elements may be ordered or grouped using a query filter:
Collection elements can be ordered or grouped using a query filter:
</para>
<programlisting><![CDATA[Collection orderedCollection = s.filter( collection, "order by this.amount" );
@ -1188,8 +1195,8 @@ Collection counts = s.filter( collection, "select this.type, count(this) group b
<title>Components</title>
<para>
Components might be used in just about every way that simple value types can be used in HQL
queries. They can appear in the <literal>select</literal> clause:
Components can be used similarly to the simple value types that are used in HQL
queries. They can appear in the <literal>select</literal> clause as follows:
</para>
<programlisting><![CDATA[select p.name from Person p]]></programlisting>
@ -1219,16 +1226,16 @@ Collection counts = s.filter( collection, "select this.type, count(this) group b
<title>Row value constructor syntax</title>
<para>
HQL supports the use of ANSI SQL <literal>row value constructor</literal> syntax (sometimes
called <literal>tuple</literal> syntax), even though the underlying database may not support
that notion. Here we are generally referring to multi-valued comparisons, typically associated
HQL supports the use of ANSI SQL <literal>row value constructor</literal> syntax, sometimes
referred to AS <literal>tuple</literal> syntax, even though the underlying database may not support
that notion. Here, we are generally referring to multi-valued comparisons, typically associated
with components. Consider an entity Person which defines a name component:
</para>
<programlisting><![CDATA[from Person p where p.name.first='John' and p.name.last='Jingleheimer-Schmidt']]></programlisting>
<para>
That's valid syntax, although a little verbose. It be nice to make this a bit more concise and use
That is valid syntax although it is a little verbose. You can make this more concise by using
<literal>row value constructor</literal> syntax:
</para>
@ -1241,8 +1248,8 @@ Collection counts = s.filter( collection, "select this.type, count(this) group b
<programlisting><![CDATA[select p.name from Person p]]></programlisting>
<para>
Another time using <literal>row value constructor</literal> syntax can be beneficial
is when using subqueries needing to compare against multiple values:
Using <literal>row value constructor</literal> syntax can also be beneficial
when using subqueries that need to compare against multiple values:
</para>
<programlisting><![CDATA[from Cat as cat
@ -1251,7 +1258,7 @@ where not ( cat.name, cat.color ) in (
)]]></programlisting>
<para>
One thing to consider when deciding if you want to use this syntax is that the query will
One thing to consider when deciding if you want to use this syntax, is that the query will
be dependent upon the ordering of the component sub-properties in the metadata.
</para>

View File

@ -28,21 +28,21 @@
<chapter id="querysql" revision="2">
<title>Native SQL</title>
<para>You may also express queries in the native SQL dialect of your
database. This is useful if you want to utilize database specific features
<para>You can also express queries in the native SQL dialect of your
database. This is useful if you want to utilize database-specific features
such as query hints or the <literal>CONNECT</literal> keyword in Oracle. It
also provides a clean migration path from a direct SQL/JDBC based
application to Hibernate.</para>
<para>Hibernate3 allows you to specify handwritten SQL (including stored
procedures) for all create, update, delete, and load operations.</para>
<para>Hibernate3 allows you to specify handwritten SQL, including stored
procedures, for all create, update, delete, and load operations.</para>
<sect1 id="querysql-creating" revision="4">
<title>Using a <literal>SQLQuery</literal></title>
<para>Execution of native SQL queries is controlled via the
<literal>SQLQuery</literal> interface, which is obtained by calling
<literal>Session.createSQLQuery()</literal>. The following describes how
<literal>Session.createSQLQuery()</literal>. The following sections describe how
to use this API for querying.</para>
<sect2>
@ -55,14 +55,14 @@
sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").list();
]]></programlisting>
<para>These will both return a List of Object arrays (Object[]) with
<para>These will return a List of Object arrays (Object[]) with
scalar values for each column in the CATS table. Hibernate will use
ResultSetMetadata to deduce the actual order and types of the returned
scalar values.</para>
<para>To avoid the overhead of using
<literal>ResultSetMetadata</literal> or simply to be more explicit in
what is returned one can use <literal>addScalar()</literal>.</para>
<literal>ResultSetMetadata</literal>, or simply to be more explicit in
what is returned, one can use <literal>addScalar()</literal>:</para>
<programlisting><![CDATA[sess.createSQLQuery("SELECT * FROM CATS")
.addScalar("ID", Hibernate.LONG)
@ -82,7 +82,7 @@ sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").list();
</listitem>
</itemizedlist>
<para>This will still return Object arrays, but now it will not use
<para>This will return Object arrays, but now it will not use
<literal>ResultSetMetadata</literal> but will instead explicitly get the
ID, NAME and BIRTHDATE column as respectively a Long, String and a Short
from the underlying resultset. This also means that only these three
@ -100,12 +100,12 @@ sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").list();
]]></programlisting>
<para>This is essentially the same query as before, but now
<literal>ResultSetMetaData</literal> is used to decide the type of NAME
and BIRTHDATE where as the type of ID is explicitly specified.</para>
<literal>ResultSetMetaData</literal> is used to determine the type of NAME
and BIRTHDATE, where as the type of ID is explicitly specified.</para>
<para>How the java.sql.Types returned from ResultSetMetaData is mapped
to Hibernate types is controlled by the Dialect. If a specific type is
not mapped or does not result in the expected type it is possible to
not mapped, or does not result in the expected type, it is possible to
customize it via calls to <literal>registerHibernateType</literal> in
the Dialect.</para>
</sect2>
@ -165,9 +165,9 @@ sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").addEntity(Cat.class)
.addJoin("cat.dog");
]]></programlisting>
<para>In this example the returned <literal>Cat</literal>'s will have
<para>In this example, the returned <literal>Cat</literal>'s will have
their <literal>dog</literal> property fully initialized without any
extra roundtrip to the database. Notice that we added a alias name
extra roundtrip to the database. Notice that you added an alias name
("cat") to be able to specify the target property path of the join. It
is possible to do the same eager joining for collections, e.g. if the
<literal>Cat</literal> had a one-to-many to <literal>Dog</literal>
@ -179,8 +179,8 @@ sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").addEntity(Cat.class)
]]></programlisting>
<para>
At this stage we are reaching the limits of what is possible with native queries without starting to
enhance the sql queries to make them usable in Hibernate; the problems starts to arise when returning
At this stage you are reaching the limits of what is possible with native queries, without starting to
enhance the sql queries to make them usable in Hibernate. Problems can arise when returning
multiple entities of the same type or when the default alias/column names are not enough.
</para>
</sect2>
@ -188,10 +188,10 @@ sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").addEntity(Cat.class)
<sect2>
<title>Returning multiple entities</title>
<para>Until now the result set column names are assumed to be the same
<para>Until now, the result set column names are assumed to be the same
as the column names specified in the mapping document. This can be
problematic for SQL queries which join multiple tables, since the same
column names may appear in more than one table.</para>
problematic for SQL queries that join multiple tables, since the same
column names can appear in more than one table.</para>
<para>Column alias injection is needed in the following query (which
most likely will fail):</para>
@ -201,12 +201,16 @@ sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").addEntity(Cat.class)
.addEntity("mother", Cat.class)
]]></programlisting>
<para>The intention for this query is to return two Cat instances per
row, a cat and its mother. This will fail since there is a conflict of
names since they are mapped to the same column names and on some
databases the returned column aliases will most likely be on the form
"c.ID", "c.NAME", etc. which are not equal to the columns specified in
the mappings ("ID" and "NAME").</para>
<para>
The query was intended to return two Cat instances per
row: a cat and its mother. The query will, however, fail because there is a conflict of
names; the instances are mapped to the same column names. Also, on some
databases the returned column aliases will most likely be on the form
"c.ID", "c.NAME", etc. which are not equal to the columns specified in
the mappings ("ID" and "NAME").
</para>
<para>The following form is not vulnerable to column name
duplication:</para>
@ -230,13 +234,13 @@ sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").addEntity(Cat.class)
</itemizedlist>
<para>The {cat.*} and {mother.*} notation used above is a shorthand for
"all properties". Alternatively, you may list the columns explicitly, but
even in this case we let Hibernate inject the SQL column aliases for
"all properties". Alternatively, you can list the columns explicitly, but
even in this case Hibernate injects the SQL column aliases for
each property. The placeholder for a column alias is just the property
name qualified by the table alias. In the following example, we retrieve
name qualified by the table alias. In the following example, you retrieve
Cats and their mothers from a different table (cat_log) to the one
declared in the mapping metadata. Notice that we may even use the
property aliases in the where clause if we like.</para>
declared in the mapping metadata. You can even use the
property aliases in the where clause.</para>
<programlisting><![CDATA[String sql = "SELECT ID as {c.id}, NAME as {c.name}, " +
"BIRTHDATE as {c.birthDate}, MOTHER_ID as {c.mother}, {mother.*} " +
@ -250,13 +254,13 @@ List loggedCats = sess.createSQLQuery(sql)
<sect3 id="querysql-aliasreferences" revision="2">
<title>Alias and property references</title>
<para>For most cases the above alias injection is needed, but for
queries relating to more complex mappings like composite properties,
inheritance discriminators, collections etc. there are some specific
aliases to use to allow Hibernate to inject the proper aliases.</para>
<para>In most cases the above alias injection is needed. For
queries relating to more complex mappings, like composite properties,
inheritance discriminators, collections etc., you can use specific
aliases that allow Hibernate to inject the proper aliases.</para>
<para>The following table shows the different possibilities of using
the alias injection. Note: the alias names in the result are examples,
<para>The following table shows the different ways you can use
the alias injection. Please note that the alias names in the result are simply examples;
each alias will have a unique and probably different name when
used.</para>
@ -339,7 +343,7 @@ List loggedCats = sess.createSQLQuery(sql)
</row>
<row>
<entry>roperty of the element in the collection</entry>
<entry>property of the element in the collection</entry>
<entry><literal>{[aliasname].element.[propertyname]}</literal></entry>
@ -370,7 +374,7 @@ List loggedCats = sess.createSQLQuery(sql)
<sect2>
<title>Returning non-managed entities</title>
<para>It is possible to apply a ResultTransformer to native sql queries. Allowing it to e.g. return non-managed entities.</para>
<para>It is possible to apply a ResultTransformer to native SQL queries, allowing it to return non-managed entities.</para>
<programlisting><![CDATA[sess.createSQLQuery("SELECT NAME, BIRTHDATE FROM CATS")
.setResultTransformer(Transformers.aliasToBean(CatDTO.class))]]></programlisting>
@ -396,15 +400,15 @@ List loggedCats = sess.createSQLQuery(sql)
<sect2>
<title>Handling inheritance</title>
<para>Native sql queries which query for entities that is mapped as part
<para>Native SQL queries which query for entities that are mapped as part
of an inheritance must include all properties for the baseclass and all
it subclasses.</para>
its subclasses.</para>
</sect2>
<sect2>
<title>Parameters</title>
<para>Native sql queries support positional as well as named
<para>Native SQL queries support positional as well as named
parameters:</para>
<programlisting><![CDATA[Query query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like ?").addEntity(Cat.class);
@ -421,8 +425,8 @@ List pusList = query.setString("name", "Pus%").list(); ]]></programlist
<sect1 id="querysql-namedqueries" revision="3">
<title>Named SQL queries</title>
<para>Named SQL queries may be defined in the mapping document and called
in exactly the same way as a named HQL query. In this case, we do
<para>Named SQL queries can be defined in the mapping document and called
in exactly the same way as a named HQL query. In this case, you do
<emphasis>not</emphasis> need to call
<literal>addEntity()</literal>.</para>
@ -440,10 +444,9 @@ List pusList = query.setString("name", "Pus%").list(); ]]></programlist
.setMaxResults(50)
.list();]]></programlisting>
<para>The <literal>&lt;return-join&gt;</literal> and
<literal>&lt;load-collection&gt;</literal> elements are used to join
associations and define queries which initialize collections,
respectively.</para>
<para>The <literal>&lt;return-join&gt;</literal> element is use to join associations and
the <literal>&lt;load-collection&gt;</literal> element is used to define queries which initialize collections,
</para>
<programlisting><![CDATA[<sql-query name="personsWith">
<return alias="person" class="eg.Person"/>
@ -473,8 +476,8 @@ List pusList = query.setString("name", "Pus%").list(); ]]></programlist
FROM PERSON p WHERE p.NAME LIKE 'Hiber%'
</sql-query>]]></programlisting>
<para>You can externalize the resultset mapping informations in a
<literal>&lt;resultset&gt;</literal> element to either reuse them across
<para>You can externalize the resultset mapping information in a
<literal>&lt;resultset&gt;</literal> element which will allow you to either reuse them across
several named queries or through the
<literal>setResultSetMapping()</literal> API.</para>
@ -497,7 +500,7 @@ List pusList = query.setString("name", "Pus%").list(); ]]></programlist
WHERE person.NAME LIKE :namePattern
</sql-query>]]></programlisting>
<para>You can alternatively use the resultset mapping information in your
<para>You can, alternatively, use the resultset mapping information in your
hbm files directly in java code.</para>
<programlisting><![CDATA[List cats = sess.createSQLQuery(
@ -510,10 +513,10 @@ List pusList = query.setString("name", "Pus%").list(); ]]></programlist
<title>Using return-property to explicitly specify column/alias
names</title>
<para>With <literal>&lt;return-property&gt;</literal> you can explicitly
tell Hibernate what column aliases to use, instead of using the
<para>You can explicitly
tell Hibernate what column aliases to use with <literal>&lt;return-property&gt;</literal>, instead of using the
<literal>{}</literal>-syntax to let Hibernate inject its own
aliases.</para>
aliases.For example:</para>
<programlisting><![CDATA[<sql-query name="mySqlQuery">
<return alias="person" class="eg.Person">
@ -530,7 +533,7 @@ List pusList = query.setString("name", "Pus%").list(); ]]></programlist
<para><literal>&lt;return-property&gt;</literal> also works with
multiple columns. This solves a limitation with the
<literal>{}</literal>-syntax which can not allow fine grained control of
<literal>{}</literal>-syntax which cannot allow fine grained control of
multi-column properties.</para>
<programlisting><![CDATA[<sql-query name="organizationCurrentEmployments">
@ -549,9 +552,9 @@ List pusList = query.setString("name", "Pus%").list(); ]]></programlist
ORDER BY STARTDATE ASC
</sql-query>]]></programlisting>
<para>Notice that in this example we used
<literal>&lt;return-property&gt;</literal> in combination with the
<literal>{}</literal>-syntax for injection. Allowing users to choose how
<para>In this example
<literal>&lt;return-property&gt;</literal> was used in combination with the
<literal>{}</literal>-syntax for injection. This allows users to choose how
they want to refer column and properties.</para>
<para>If your mapping has a discriminator you must use
@ -562,7 +565,7 @@ List pusList = query.setString("name", "Pus%").list(); ]]></programlist
<sect2 id="sp_query" revision="1">
<title>Using stored procedures for querying</title>
<para>Hibernate 3 introduces support for queries via stored procedures
<para>Hibernate3 provides support for queries via stored procedures
and functions. Most of the following documentation is equivalent for
both. The stored procedure/function must return a resultset as the first
out-parameter to be able to work with Hibernate. An example of such a
@ -600,24 +603,24 @@ BEGIN
{ ? = call selectAllEmployments() }
</sql-query>]]></programlisting>
<para>Notice stored procedures currently only return scalars and
<para>Stored procedures currently only return scalars and
entities. <literal>&lt;return-join&gt;</literal> and
<literal>&lt;load-collection&gt;</literal> are not supported.</para>
<sect3 id="querysql-limits-storedprocedures" revision="1">
<title>Rules/limitations for using stored procedures</title>
<para>To use stored procedures with Hibernate the procedures/functions
have to follow some rules. If they do not follow those rules they are
<para>You cannot use stored procedures with Hibernate unless you follow some procedure/function
rules. If they do not follow those rules they are
not usable with Hibernate. If you still want to use these procedures
you have to execute them via <literal>session.connection()</literal>.
The rules are different for each database, since database vendors have
different stored procedure semantics/syntax.</para>
<para>Stored procedure queries can't be paged with
<para>Stored procedure queries cannot be paged with
<literal>setFirstResult()/setMaxResults()</literal>.</para>
<para>Recommended call form is standard SQL92: <literal>{ ? = call
<para>The recommended call form is standard SQL92: <literal>{ ? = call
functionName(&lt;parameters&gt;) }</literal> or <literal>{ ? = call
procedureName(&lt;parameters&gt;}</literal>. Native call syntax is not
supported.</para>
@ -630,8 +633,8 @@ BEGIN
a procedure must be an <literal>OUT</literal> that returns a
result set. This is done by using a
<literal>SYS_REFCURSOR</literal> type in Oracle 9 or 10. In Oracle
you need to define a <literal>REF CURSOR</literal> type, see
Oracle literature.</para>
you need to define a <literal>REF CURSOR</literal> type. See
Oracle literature for further information.</para>
</listitem>
</itemizedlist>
@ -640,7 +643,7 @@ BEGIN
<itemizedlist spacing="compact">
<listitem>
<para>The procedure must return a result set. Note that since
these servers can/will return multiple result sets and update
these servers can return multiple result sets and update
counts, Hibernate will iterate the results and take the first
result that is a result set as its return value. Everything else
will be discarded.</para>
@ -677,8 +680,8 @@ BEGIN
<sql-delete>DELETE FROM PERSON WHERE ID=?</sql-delete>
</class>]]></programlisting>
<para>The SQL is directly executed in your database, so you are free to
use any dialect you like. This will of course reduce the portability of
<para>The SQL is directly executed in your database, so you can
use any dialect you like. This will reduce the portability of
your mapping if you use database specific SQL.</para>
<para>Stored procedures are supported if the <literal>callable</literal>
@ -694,18 +697,18 @@ BEGIN
<sql-update callable="true">{? = call updatePerson (?, ?)}</sql-update>
</class>]]></programlisting>
<para>The order of the positional parameters are currently vital, as they
<para>The order of the positional parameters is vital, as they
must be in the same sequence as Hibernate expects them.</para>
<para>You can see the expected order by enabling debug logging for the
<para>You can view the expected order by enabling debug logging for the
<literal>org.hibernate.persister.entity</literal> level. With this level
enabled Hibernate will print out the static SQL that is used to create,
update, delete etc. entities. (To see the expected sequence, remember to
not include your custom SQL in the mapping files as that will override the
Hibernate generated static sql.)</para>
enabled, Hibernate will print out the static SQL that is used to create,
update, delete etc. entities. To view the expected sequence, do
not include your custom SQL in the mapping files, as this will override the
Hibernate generated static SQL.</para>
<para>The stored procedures are in most cases (read: better do it than
not) required to return the number of rows inserted/updated/deleted, as
<para>The stored procedures are in most cases
required to return the number of rows inserted, updated and deleted, as
Hibernate has some runtime checks for the success of the statement.
Hibernate always registers the first statement parameter as a numeric
output parameter for the CUD operations:</para>
@ -728,7 +731,7 @@ END updatePerson;]]></programlisting>
<sect1 id="querysql-load">
<title>Custom SQL for loading</title>
<para>You may also declare your own SQL (or HQL) queries for entity
<para>You can also declare your own SQL (or HQL) queries for entity
loading:</para>
<programlisting><![CDATA[<sql-query name="person">
@ -740,7 +743,7 @@ END updatePerson;]]></programlisting>
</sql-query>]]></programlisting>
<para>This is just a named query declaration, as discussed earlier. You
may reference this named query in a class mapping:</para>
can reference this named query in a class mapping:</para>
<programlisting><![CDATA[<class name="Person">
<id name="id">
@ -752,7 +755,7 @@ END updatePerson;]]></programlisting>
<para>This even works with stored procedures.</para>
<para>You may even define a query for collection loading:</para>
<para>You can even define a query for collection loading:</para>
<programlisting><![CDATA[<set name="employments" inverse="true">
<key/>
@ -768,7 +771,7 @@ END updatePerson;]]></programlisting>
ORDER BY STARTDATE ASC, EMPLOYEE ASC
</sql-query>]]></programlisting>
<para>You could even define an entity loader that loads a collection by
<para>You can also define an entity loader that loads a collection by
join fetching:</para>
<programlisting><![CDATA[<sql-query name="person">

View File

@ -33,7 +33,7 @@
the developer from the details of the underlying database management
system, but also offers <emphasis>state management</emphasis> of objects. This is,
contrary to the management of SQL <literal>statements</literal> in common JDBC/SQL
persistence layers, a very natural object-oriented view of persistence in Java
persistence layers, a natural object-oriented view of persistence in Java
applications.
</para>
@ -59,7 +59,7 @@
is not associated with a Hibernate <literal>Session</literal>. It has no
persistent representation in the database and no identifier value has been
assigned. Transient instances will be destroyed by the garbage collector if
the application doesn't hold a reference anymore. Use the Hibernate
the application does not hold a reference anymore. Use the Hibernate
<literal>Session</literal> to make an object persistent (and let Hibernate
take care of the SQL statements that need to be executed for this transition).
</para>
@ -71,7 +71,7 @@
however, it is by definition in the scope of a <literal>Session</literal>.
Hibernate will detect any changes made to an object in persistent state and
synchronize the state with the database when the unit of work completes.
Developers don't execute manual <literal>UPDATE</literal> statements, or
Developers do not execute manual <literal>UPDATE</literal> statements, or
<literal>DELETE</literal> statements when an object should be made transient.
</para>
</listitem>
@ -84,14 +84,14 @@
<literal>Session</literal> at a later point in time, making it (and all the
modifications) persistent again. This feature enables a programming model for
long running units of work that require user think-time. We call them
<emphasis>application transactions</emphasis>, i.e. a unit of work from the
<emphasis>application transactions</emphasis>, i.e., a unit of work from the
point of view of the user.
</para>
</listitem>
</itemizedlist>
<para>
We'll now discuss the states and state transitions (and the Hibernate methods that
We will now discuss the states and state transitions (and the Hibernate methods that
trigger a transition) in more detail.
</para>
@ -119,7 +119,7 @@ Long generatedId = (Long) sess.save(fritz);]]></programlisting>
is called. If <literal>Cat</literal> has an <literal>assigned</literal>
identifier, or a composite key, the identifier should be assigned to
the <literal>cat</literal> instance before calling <literal>save()</literal>.
You may also use <literal>persist()</literal> instead of <literal>save()</literal>,
You can also use <literal>persist()</literal> instead of <literal>save()</literal>,
with the semantics defined in the EJB3 early draft.
</para>
@ -127,7 +127,7 @@ Long generatedId = (Long) sess.save(fritz);]]></programlisting>
<listitem>
<para>
<literal>persist()</literal> makes a transient instance persistent.
However, it doesn't guarantee that the identifier value will be assigned to
However, it does not guarantee that the identifier value will be assigned to
the persistent instance immediately, the assignment might happen at flush time.
<literal>persist()</literal> also guarantees that it will not execute an
<literal>INSERT</literal> statement if it is called outside of transaction
@ -147,7 +147,7 @@ Long generatedId = (Long) sess.save(fritz);]]></programlisting>
</itemizedlist>
<para>
Alternatively, you may assign the identifier using an overloaded version
Alternatively, you can assign the identifier using an overloaded version
of <literal>save()</literal>.
</para>
@ -162,7 +162,7 @@ sess.save( pk, new Long(1234) );]]></programlisting>
<para>
If the object you make persistent has associated objects (e.g. the
<literal>kittens</literal> collection in the previous example),
these objects may be made persistent in any order you like unless you
these objects can be made persistent in any order you like unless you
have a <literal>NOT NULL</literal> constraint upon a foreign key column.
There is never a risk of violating foreign key constraints. However, you
might violate a <literal>NOT NULL</literal> constraint if you
@ -170,10 +170,10 @@ sess.save( pk, new Long(1234) );]]></programlisting>
</para>
<para>
Usually you don't bother with this detail, as you'll very likely use Hibernate's
Usually you do not bother with this detail, as you will normally use Hibernate's
<emphasis>transitive persistence</emphasis> feature to save the associated
objects automatically. Then, even <literal>NOT NULL</literal>
constraint violations don't occur - Hibernate will take care of everything.
constraint violations do not occur - Hibernate will take care of everything.
Transitive persistence is discussed later in this chapter.
</para>
@ -183,10 +183,10 @@ sess.save( pk, new Long(1234) );]]></programlisting>
<title>Loading an object</title>
<para>
The <literal>load()</literal> methods of <literal>Session</literal> gives you
a way to retrieve a persistent instance if you already know its identifier.
<literal>load()</literal> takes a class object and will load the state into
a newly instantiated instance of that class, in persistent state.
The <literal>load()</literal> methods of <literal>Session</literal> provide
a way of retrieving a persistent instance if you know its identifier.
<literal>load()</literal> takes a class object and loads the state into
a newly instantiated instance of that class in a persistent state.
</para>
<programlisting><![CDATA[Cat fritz = (Cat) sess.load(Cat.class, generatedId);]]></programlisting>
@ -205,11 +205,11 @@ sess.load( cat, new Long(pkId) );
Set kittens = cat.getKittens();]]></programlisting>
<para>
Note that <literal>load()</literal> will throw an unrecoverable exception if
Be aware that <literal>load()</literal> will throw an unrecoverable exception if
there is no matching database row. If the class is mapped with a proxy,
<literal>load()</literal> just returns an uninitialized proxy and does not
actually hit the database until you invoke a method of the proxy. This
behaviour is very useful if you wish to create an association to an object
is useful if you wish to create an association to an object
without actually loading it from the database. It also allows multiple
instances to be loaded as a batch if <literal>batch-size</literal> is
defined for the class mapping.
@ -217,7 +217,7 @@ Set kittens = cat.getKittens();]]></programlisting>
<para>
If you are not certain that a matching row exists, you should use the
<literal>get()</literal> method, which hits the database immediately and
<literal>get()</literal> method which hits the database immediately and
returns null if there is no matching row.
</para>
@ -229,15 +229,15 @@ if (cat==null) {
return cat;]]></programlisting>
<para>
You may even load an object using an SQL <literal>SELECT ... FOR UPDATE</literal>,
You can even load an object using an SQL <literal>SELECT ... FOR UPDATE</literal>,
using a <literal>LockMode</literal>. See the API documentation for more information.
</para>
<programlisting><![CDATA[Cat cat = (Cat) sess.get(Cat.class, id, LockMode.UPGRADE);]]></programlisting>
<para>
Note that any associated instances or contained collections are
<emphasis>not</emphasis> selected <literal>FOR UPDATE</literal>, unless you decide
Any associated instances or contained collections will
<emphasis>not</emphasis> be selected <literal>FOR UPDATE</literal>, unless you decide
to specify <literal>lock</literal> or <literal>all</literal> as a
cascade style for the association.
</para>
@ -253,9 +253,9 @@ sess.flush(); //force the SQL INSERT
sess.refresh(cat); //re-read the state (after the trigger executes)]]></programlisting>
<para>
An important question usually appears at this point: How much does Hibernate load
How much does Hibernate load
from the database and how many SQL <literal>SELECT</literal>s will it use? This
depends on the <emphasis>fetching strategy</emphasis> and is explained in
depends on the <emphasis>fetching strategy</emphasis>. This is explained in
<xref linkend="performance-fetching"/>.
</para>
@ -265,11 +265,11 @@ sess.refresh(cat); //re-read the state (after the trigger executes)]]></programl
<title>Querying</title>
<para>
If you don't know the identifiers of the objects you are looking for,
If you do not know the identifiers of the objects you are looking for,
you need a query. Hibernate supports an easy-to-use but powerful object
oriented query language (HQL). For programmatic query creation, Hibernate
supports a sophisticated Criteria and Example query feature (QBC and QBE).
You may also express your query in the native SQL of your database, with
You can also express your query in the native SQL of your database, with
optional support from Hibernate for result set conversion into objects.
</para>
@ -308,14 +308,14 @@ Query mothersWithKittens = (Cat) session.createQuery(
Set uniqueMothers = new HashSet(mothersWithKittens.list());]]></programlisting>
<para>
A query is usually executed by invoking <literal>list()</literal>, the
A query is usually executed by invoking <literal>list()</literal>. The
result of the query will be loaded completely into a collection in memory.
Entity instances retrieved by a query are in persistent state. The
Entity instances retrieved by a query are in a persistent state. The
<literal>uniqueResult()</literal> method offers a shortcut if you
know your query will only return a single object. Note that queries that
know your query will only return a single object. Queries that
make use of eager fetching of collections usually return duplicates of
the root objects (but with their collections initialized). You can filter
these duplicates simply through a <literal>Set</literal>.
the root objects, but with their collections initialized. You can filter
these duplicates through a <literal>Set</literal>.
</para>
<sect3 id="objectstate-querying-executing-iterate">
@ -324,7 +324,7 @@ Set uniqueMothers = new HashSet(mothersWithKittens.list());]]></programlisting>
<para>
Occasionally, you might be able to achieve better performance by
executing the query using the <literal>iterate()</literal> method.
This will only usually be the case if you expect that the actual
This will usually be the case if you expect that the actual
entity instances returned by the query will already be in the session
or second-level cache. If they are not already cached,
<literal>iterate()</literal> will be slower than <literal>list()</literal>
@ -351,7 +351,7 @@ while ( iter.hasNext() ) {
<title>Queries that return tuples</title>
<para>
Hibernate queries sometimes return tuples of objects, in which case each tuple
Hibernate queries sometimes return tuples of objects. Each tuple
is returned as an array:
</para>
@ -373,9 +373,9 @@ while ( kittensAndMothers.hasNext() ) {
<title>Scalar results</title>
<para>
Queries may specify a property of a class in the <literal>select</literal> clause.
They may even call SQL aggregate functions. Properties or aggregates are considered
"scalar" results (and not entities in persistent state).
Queries can specify a property of a class in the <literal>select</literal> clause.
They can even call SQL aggregate functions. Properties or aggregates are considered
"scalar" results and not entities in persistent state.
</para>
<programlisting><![CDATA[Iterator results = sess.createQuery(
@ -402,7 +402,7 @@ while ( results.hasNext() ) {
named parameters or JDBC-style <literal>?</literal> parameters.
<emphasis>Contrary to JDBC, Hibernate numbers parameters from zero.</emphasis>
Named parameters are identifiers of the form <literal>:name</literal> in
the query string. The advantages of named parameters are:
the query string. The advantages of named parameters are as follows:
</para>
<itemizedlist spacing="compact">
@ -414,7 +414,7 @@ while ( results.hasNext() ) {
</listitem>
<listitem>
<para>
they may occur multiple times in the same query
they can occur multiple times in the same query
</para>
</listitem>
<listitem>
@ -448,8 +448,8 @@ List cats = q.list();]]></programlisting>
<title>Pagination</title>
<para>
If you need to specify bounds upon your result set (the maximum number of rows
you want to retrieve and / or the first row you want to retrieve) you should
If you need to specify bounds upon your result set, that is, the maximum number of rows
you want to retrieve and/or the first row you want to retrieve, you can
use methods of the <literal>Query</literal> interface:
</para>
@ -470,8 +470,8 @@ List cats = q.list();]]></programlisting>
<para>
If your JDBC driver supports scrollable <literal>ResultSet</literal>s, the
<literal>Query</literal> interface may be used to obtain a
<literal>ScrollableResults</literal> object, which allows flexible
<literal>Query</literal> interface can be used to obtain a
<literal>ScrollableResults</literal> object that allows flexible
navigation of the query results.
</para>
@ -498,8 +498,8 @@ if ( cats.first() ) {
cats.close()]]></programlisting>
<para>
Note that an open database connection (and cursor) is required for this
functionality, use <literal>setMaxResult()</literal>/<literal>setFirstResult()</literal>
Note that an open database connection and cursor is required for this
functionality. Use <literal>setMaxResult()</literal>/<literal>setFirstResult()</literal>
if you need offline pagination functionality.
</para>
@ -509,9 +509,9 @@ cats.close()]]></programlisting>
<title>Externalizing named queries</title>
<para>
You may also define named queries in the mapping document. (Remember to use a
You can also define named queries in the mapping document. Remember to use a
<literal>CDATA</literal> section if your query contains characters that could
be interpreted as markup.)
be interpreted as markup.
</para>
<programlisting><![CDATA[<query name="ByNameAndMaximumWeight"><![CDATA[
@ -530,8 +530,8 @@ q.setInt(1, minWeight);
List cats = q.list();]]></programlisting>
<para>
Note that the actual program code is independent of the query language that
is used, you may also define native SQL queries in metadata, or migrate
The actual program code is independent of the query language that
is used. You can also define native SQL queries in metadata, or migrate
existing queries to Hibernate by placing them in mapping files.
</para>
@ -539,7 +539,7 @@ List cats = q.list();]]></programlisting>
Also note that a query declaration inside a <literal>&lt;hibernate-mapping&gt;</literal>
element requires a global unique name for the query, while a query declaration inside a
<literal>&lt;class&gt;</literal> element is made unique automatically by prepending the
fully qualified name of the class, for example
fully qualified name of the class. For example
<literal>eg.Cat.ByNameAndMaximumWeight</literal>.
</para>
@ -550,8 +550,8 @@ List cats = q.list();]]></programlisting>
<sect2 id="objectstate-filtering" revision="1">
<title>Filtering collections</title>
<para>
A collection <emphasis>filter</emphasis> is a special type of query that may be applied to
a persistent collection or array. The query string may refer to <literal>this</literal>,
A collection <emphasis>filter</emphasis> is a special type of query that can be applied to
a persistent collection or array. The query string can refer to <literal>this</literal>,
meaning the current collection element.
</para>
@ -563,14 +563,14 @@ List cats = q.list();]]></programlisting>
);]]></programlisting>
<para>
The returned collection is considered a bag, and it's a copy of the given
collection. The original collection is not modified (this is contrary to
the implication of the name "filter", but consistent with expected behavior).
The returned collection is considered a bag that is a copy of the given
collection. The original collection is not modified. This is contrary to
the implication of the name "filter", but consistent with expected behavior.
</para>
<para>
Observe that filters do not require a <literal>from</literal> clause (though they may have
one if required). Filters are not limited to returning the collection elements themselves.
Observe that filters do not require a <literal>from</literal> clause, although they can have
one if required. Filters are not limited to returning the collection elements themselves.
</para>
<programlisting><![CDATA[Collection blackKittenMates = session.createFilter(
@ -580,7 +580,7 @@ List cats = q.list();]]></programlisting>
<para>
Even an empty filter query is useful, e.g. to load a subset of elements in a
huge collection:
large collection:
</para>
<programlisting><![CDATA[Collection tenKittens = session.createFilter(
@ -594,7 +594,7 @@ List cats = q.list();]]></programlisting>
<title>Criteria queries</title>
<para>
HQL is extremely powerful but some developers prefer to build queries dynamically,
HQL is extremely powerful, but some developers prefer to build queries dynamically
using an object-oriented API, rather than building query strings. Hibernate provides
an intuitive <literal>Criteria</literal> query API for these cases:
</para>
@ -615,10 +615,10 @@ List cats = crit.list();]]></programlisting>
<title>Queries in native SQL</title>
<para>
You may express a query in SQL, using <literal>createSQLQuery()</literal> and
let Hibernate take care of the mapping from result sets to objects. Note
that you may at any time call <literal>session.connection()</literal> and
use the JDBC <literal>Connection</literal> directly. If you chose to use the
You can express a query in SQL, using <literal>createSQLQuery()</literal> and
let Hibernate manage the mapping from result sets to objects.
You can at any time call <literal>session.connection()</literal> and
use the JDBC <literal>Connection</literal> directly. If you choose to use the
Hibernate API, you must enclose SQL aliases in braces:
</para>
@ -634,7 +634,7 @@ List cats = crit.list();]]></programlisting>
.list()]]></programlisting>
<para>
SQL queries may contain named and positional parameters, just like Hibernate queries.
SQL queries can contain named and positional parameters, just like Hibernate queries.
More information about native SQL queries in Hibernate can be found in
<xref linkend="querysql"/>.
</para>
@ -647,14 +647,14 @@ List cats = crit.list();]]></programlisting>
<title>Modifying persistent objects</title>
<para>
<emphasis>Transactional persistent instances</emphasis> (ie. objects loaded, saved, created or
queried by the <literal>Session</literal>) may be manipulated by the application
<emphasis>Transactional persistent instances</emphasis> (i.e. objects loaded, saved, created or
queried by the <literal>Session</literal>) can be manipulated by the application,
and any changes to persistent state will be persisted when the <literal>Session</literal>
is <emphasis>flushed</emphasis> (discussed later in this chapter). There is no need
is <emphasis>flushed</emphasis>. This is discussed later in this chapter. There is no need
to call a particular method (like <literal>update()</literal>, which has a different
purpose) to make your modifications persistent. So the most straightforward way to update
the state of an object is to <literal>load()</literal> it,
and then manipulate it directly, while the <literal>Session</literal> is open:
purpose) to make your modifications persistent. The most straightforward way to update
the state of an object is to <literal>load()</literal> it
and then manipulate it directly while the <literal>Session</literal> is open:
</para>
<programlisting><![CDATA[DomesticCat cat = (DomesticCat) sess.load( Cat.class, new Long(69) );
@ -662,24 +662,25 @@ cat.setName("PK");
sess.flush(); // changes to cat are automatically detected and persisted]]></programlisting>
<para>
Sometimes this programming model is inefficient since it would require both an SQL
<literal>SELECT</literal> (to load an object) and an SQL <literal>UPDATE</literal>
(to persist its updated state) in the same session. Therefore Hibernate offers an
alternate approach, using detached instances.
Sometimes this programming model is inefficient, as it requires in the same session both an SQL
<literal>SELECT</literal> to load an object and an SQL <literal>UPDATE</literal>
to persist its updated state. Hibernate offers an
alternate approach by using detached instances.
</para>
<para>
<emphasis>Note that Hibernate does not offer its own API for direct execution of
<important><para>
Hibernate does not offer its own API for direct execution of
<literal>UPDATE</literal> or <literal>DELETE</literal> statements. Hibernate is a
<emphasis>state management</emphasis> service, you don't have to think in
<emphasis>state management</emphasis> service, you do not have to think in
<emphasis>statements</emphasis> to use it. JDBC is a perfect API for executing
SQL statements, you can get a JDBC <literal>Connection</literal> at any time
by calling <literal>session.connection()</literal>. Furthermore, the notion
of mass operations conflicts with object/relational mapping for online
transaction processing-oriented applications. Future versions of Hibernate
may however provide special mass operation functions. See <xref linkend="batch"/>
for some possible batch operation tricks.</emphasis>
can, however, provide special mass operation functions. See <xref linkend="batch"/>
for some possible batch operation tricks.
</para>
</important>
</sect1>
@ -690,7 +691,7 @@ sess.flush(); // changes to cat are automatically detected and persisted]]></pr
Many applications need to retrieve an object in one transaction, send it to the
UI layer for manipulation, then save the changes in a new transaction.
Applications that use this kind of approach in a high-concurrency environment
usually use versioned data to ensure isolation for the "long" unit of work.
usually use versioned data to ensure isolation for the "long" unit of work.
</para>
<para>
@ -713,29 +714,29 @@ secondSession.update(mate); // update mate]]></programlisting>
<para>
If the <literal>Cat</literal> with identifier <literal>catId</literal> had already
been loaded by <literal>secondSession</literal> when the application tried to
been loaded by <literal>secondSession</literal> when the application tried to
reattach it, an exception would have been thrown.
</para>
<para>
Use <literal>update()</literal> if you are sure that the session does
not contain an already persistent instance with the same identifier, and
Use <literal>update()</literal> if you are certain that the session does
not contain an already persistent instance with the same identifier. Use
<literal>merge()</literal> if you want to merge your modifications at any time
without consideration of the state of the session. In other words, <literal>update()</literal>
is usually the first method you would call in a fresh session, ensuring that
reattachment of your detached instances is the first operation that is executed.
the reattachment of your detached instances is the first operation that is executed.
</para>
<para>
The application should individually <literal>update()</literal> detached instances
reachable from the given detached instance if and <emphasis>only</emphasis> if it wants
their state also updated. This can be automated of course, using <emphasis>transitive
persistence</emphasis>, see <xref linkend="objectstate-transitive"/>.
that are reachable from the given detached instance <emphasis>only</emphasis> if it wants
their state to be updated. This can be automated using <emphasis>transitive
persistence</emphasis>. See <xref linkend="objectstate-transitive"/> for more information.
</para>
<para>
The <literal>lock()</literal> method also allows an application to reassociate
an object with a new session. However, the detached instance has to be unmodified!
an object with a new session. However, the detached instance has to be unmodified.
</para>
<programlisting><![CDATA[//just reassociate:
@ -747,7 +748,7 @@ sess.lock(pk, LockMode.UPGRADE);]]></programlisting>
<para>
Note that <literal>lock()</literal> can be used with various
<literal>LockMode</literal>s, see the API documentation and the
<literal>LockMode</literal>s. See the API documentation and the
chapter on transaction handling for more information. Reattachment is not
the only usecase for <literal>lock()</literal>.
</para>
@ -850,8 +851,8 @@ secondSession.saveOrUpdate(mate); // save the new instance (mate has a null id)
</listitem>
<listitem>
<para>
if the object is versioned (by a <literal>&lt;version&gt;</literal> or
<literal>&lt;timestamp&gt;</literal>), and the version property value
if the object is versioned by a <literal>&lt;version&gt;</literal> or
<literal>&lt;timestamp&gt;</literal>, and the version property value
is the same value assigned to a newly instantiated object,
<literal>save()</literal> it
</para>
@ -901,15 +902,15 @@ secondSession.saveOrUpdate(mate); // save the new instance (mate has a null id)
<para>
<literal>Session.delete()</literal> will remove an object's state from the database.
Of course, your application might still hold a reference to a deleted object.
It's best to think of <literal>delete()</literal> as making a persistent instance
Your application, however, can still hold a reference to a deleted object.
It is best to think of <literal>delete()</literal> as making a persistent instance,
transient.
</para>
<programlisting><![CDATA[sess.delete(cat);]]></programlisting>
<para>
You may delete objects in any order you like, without risk of foreign key
You can delete objects in any order, without risk of foreign key
constraint violations. It is still possible to violate a <literal>NOT
NULL</literal> constraint on a foreign key column by deleting objects in
the wrong order, e.g. if you delete the parent, but forget to delete the
@ -922,7 +923,7 @@ secondSession.saveOrUpdate(mate); // save the new instance (mate has a null id)
<title>Replicating object between two different datastores</title>
<para>
It is occasionally useful to be able to take a graph of persistent instances
It is sometimes useful to be able to take a graph of persistent instances
and make them persistent in a different datastore, without regenerating identifier
values.
</para>
@ -943,31 +944,31 @@ session2.close();]]></programlisting>
<para>
The <literal>ReplicationMode</literal> determines how <literal>replicate()</literal>
will deal with conflicts with existing rows in the database.
will deal with conflicts with existing rows in the database:
</para>
<itemizedlist spacing="compact">
<listitem>
<para>
<literal>ReplicationMode.IGNORE</literal> - ignore the object when there is
<literal>ReplicationMode.IGNORE</literal>: ignores the object when there is
an existing database row with the same identifier
</para>
</listitem>
<listitem>
<para>
<literal>ReplicationMode.OVERWRITE</literal> - overwrite any existing database
<literal>ReplicationMode.OVERWRITE</literal>: overwrites any existing database
row with the same identifier
</para>
</listitem>
<listitem>
<para>
<literal>ReplicationMode.EXCEPTION</literal> - throw an exception if there is
<literal>ReplicationMode.EXCEPTION</literal>: throws an exception if there is
an existing database row with the same identifier
</para>
</listitem>
<listitem>
<para>
<literal>ReplicationMode.LATEST_VERSION</literal> - overwrite the row if its
<literal>ReplicationMode.LATEST_VERSION</literal>: overwrites the row if its
version number is earlier than the version number of the object, or ignore
the object otherwise
</para>
@ -986,10 +987,10 @@ session2.close();]]></programlisting>
<title>Flushing the Session</title>
<para>
From time to time the <literal>Session</literal> will execute the SQL statements
Sometimes the <literal>Session</literal> will execute the SQL statements
needed to synchronize the JDBC connection's state with the state of objects held in
memory. This process, <emphasis>flush</emphasis>, occurs by default at the following
points
memory. This process, called <emphasis>flush</emphasis>, occurs by default at the following
points:
</para>
<itemizedlist spacing="compact">
@ -1011,13 +1012,13 @@ session2.close();]]></programlisting>
</itemizedlist>
<para>
The SQL statements are issued in the following order
The SQL statements are issued in the following order:
</para>
<orderedlist spacing="compact">
<listitem>
<para>
all entity insertions, in the same order the corresponding objects
all entity insertions in the same order the corresponding objects
were saved using <literal>Session.save()</literal>
</para>
</listitem>
@ -1043,30 +1044,30 @@ session2.close();]]></programlisting>
</listitem>
<listitem>
<para>
all entity deletions, in the same order the corresponding objects
all entity deletions in the same order the corresponding objects
were deleted using <literal>Session.delete()</literal>
</para>
</listitem>
</orderedlist>
<para>
(An exception is that objects using <literal>native</literal> ID generation are
inserted when they are saved.)
An exception is that objects using <literal>native</literal> ID generation are
inserted when they are saved.
</para>
<para>
Except when you explicity <literal>flush()</literal>, there are absolutely no
Except when you explicitly <literal>flush()</literal>, there are absolutely no
guarantees about <emphasis>when</emphasis> the <literal>Session</literal> executes
the JDBC calls, only the <emphasis>order</emphasis> in which they are executed.
However, Hibernate does guarantee that the <literal>Query.list(..)</literal>
will never return stale data; nor will they return the wrong data.
will never return stale or incorrect data.
</para>
<para>
It is possible to change the default behavior so that flush occurs less frequently.
The <literal>FlushMode</literal> class defines three different modes: only flush
at commit time (and only when the Hibernate <literal>Transaction</literal> API
is used), flush automatically using the explained routine, or never flush unless
at commit time when the Hibernate <literal>Transaction</literal> API
is used, flush automatically using the explained routine, or never flush unless
<literal>flush()</literal> is called explicitly. The last mode is useful for long running
units of work, where a <literal>Session</literal> is kept open and disconnected for
a long time (see <xref linkend="transactions-optimistic-longsession"/>).
@ -1108,17 +1109,17 @@ sess.close();]]></programlisting>
If the children in a parent/child relationship would be value typed (e.g. a collection
of addresses or strings), their life cycle would depend on the parent and no
further action would be required for convenient "cascading" of state changes.
When the parent is saved, the value-typed child objects are saved as
well, when the parent is deleted, the children will be deleted, etc. This
even works for operations such as the removal of a child from the collection;
Hibernate will detect this and, since value-typed objects can't have shared
references, delete the child from the database.
When the parent is saved, the value-typed child objects are saved and
when the parent is deleted, the children will be deleted, etc. This
works for operations such as the removal of a child from the collection.
Since value-typed objects cannot have shared
references, Hibernate will detect this and delete the child from the database.
</para>
<para>
Now consider the same scenario with parent and child objects being entities,
not value-types (e.g. categories and items, or parent and child cats). Entities
have their own life cycle, support shared references (so removing an entity from
have their own life cycle and support shared references. Removing an entity from
the collection does not mean it can be deleted), and there is by default no
cascading of state from one entity to any other associated entities. Hibernate
does not implement <emphasis>persistence by reachability</emphasis> by default.
@ -1142,7 +1143,7 @@ sess.close();]]></programlisting>
<programlisting><![CDATA[<one-to-one name="person" cascade="persist,delete,lock"/>]]></programlisting>
<para>
You may even use <literal>cascade="all"</literal> to specify that <emphasis>all</emphasis>
You can even use <literal>cascade="all"</literal> to specify that <emphasis>all</emphasis>
operations should be cascaded along the association. The default <literal>cascade="none"</literal>
specifies that no operations are to be cascaded.
</para>
@ -1161,7 +1162,7 @@ sess.close();]]></programlisting>
<itemizedlist spacing="compact">
<listitem>
<para>
It doesn't usually make sense to enable cascade on a <literal>&lt;many-to-one&gt;</literal>
It does not usually make sense to enable cascade on a <literal>&lt;many-to-one&gt;</literal>
or <literal>&lt;many-to-many&gt;</literal> association. Cascade is often useful for
<literal>&lt;one-to-one&gt;</literal> and <literal>&lt;one-to-many&gt;</literal>
associations.
@ -1190,7 +1191,7 @@ sess.close();]]></programlisting>
parent results in save/update/delete of the child or children.
</para>
<para>
Futhermore, a mere reference to a child from a persistent parent will result in
Furthermore, a mere reference to a child from a persistent parent will result in
save/update of the child. This metaphor is incomplete, however. A child which becomes
unreferenced by its parent is <emphasis>not</emphasis> automatically deleted, except
in the case of a <literal>&lt;one-to-many&gt;</literal> association mapped with
@ -1242,7 +1243,7 @@ sess.close();]]></programlisting>
Finally, note that cascading of operations can be applied to an object graph at
<emphasis>call time</emphasis> or at <emphasis>flush time</emphasis>. All operations,
if enabled, are cascaded to associated entities reachable when the operation is
executed. However, <literal>save-upate</literal> and <literal>delete-orphan</literal>
executed. However, <literal>save-update</literal> and <literal>delete-orphan</literal>
are transitive for all associated entities reachable during flush of the
<literal>Session</literal>.
</para>
@ -1253,16 +1254,16 @@ sess.close();]]></programlisting>
<title>Using metadata</title>
<para>
Hibernate requires a very rich meta-level model of all entity and value types. From time
to time, this model is very useful to the application itself. For example, the application
Hibernate requires a rich meta-level model of all entity and value types.
This model can be useful to the application itself. For example, the application
might use Hibernate's metadata to implement a "smart" deep-copy algorithm that understands
which objects should be copied (eg. mutable value types) and which should not (eg.
which objects should be copied (eg. mutable value types) and which objects that should not (e.g.
immutable value types and, possibly, associated entities).
</para>
<para>
Hibernate exposes metadata via the <literal>ClassMetadata</literal> and
<literal>CollectionMetadata</literal> interfaces and the <literal>Type</literal>
hierarchy. Instances of the metadata interfaces may be obtained from the
hierarchy. Instances of the metadata interfaces can be obtained from the
<literal>SessionFactory</literal>.
</para>

View File

@ -30,57 +30,57 @@
<para>
Roundtrip engineering with Hibernate is possible using a set of Eclipse plugins,
commandline tools, as well as Ant tasks.
commandline tools, and Ant tasks.
</para>
<para>
The <emphasis>Hibernate Tools</emphasis> currently include plugins for the Eclipse
<emphasis>Hibernate Tools</emphasis> currently include plugins for the Eclipse
IDE as well as Ant tasks for reverse engineering of existing databases:
</para>
<itemizedlist>
<listitem><para>
<emphasis>Mapping Editor:</emphasis> An editor for Hibernate XML mapping files,
supporting auto-completion and syntax highlighting. It also supports semantic
auto-completion for class names and property/field names, making it much more versatile than a normal XML editor.
<emphasis>Mapping Editor:</emphasis> an editor for Hibernate XML mapping files that
supports auto-completion and syntax highlighting. It also supports semantic
auto-completion for class names and property/field names, making it more versatile than a normal XML editor.
</para></listitem>
<listitem><para>
<emphasis>Console:</emphasis> The console is a new view in Eclipse. In addition to
a tree overview of your console configurations, you also get an interactive view
<emphasis>Console:</emphasis> the console is a new view in Eclipse. In addition to
a tree overview of your console configurations, you are also provided with an interactive view
of your persistent classes and their relationships. The console allows you to
execute HQL queries against your database and browse the result directly in
Eclipse.
</para></listitem>
<listitem><para>
<emphasis>Development Wizards:</emphasis> Several wizards are provided with the
Hibernate Eclipse tools; you can use a wizard to quickly generate Hibernate configuration
(cfg.xml) files, or you may even completely reverse engineer an existing database schema
<emphasis>Development Wizards:</emphasis> several wizards are provided with the
Hibernate Eclipse tools. You can use a wizard to quickly generate Hibernate configuration
(cfg.xml) files, or to reverse engineer an existing database schema
into POJO source files and Hibernate mapping files. The reverse engineering wizard
supports customizable templates.
</para></listitem>
<listitem><para>
<emphasis>Ant Tasks:</emphasis>
<!-- <emphasis>Ant Tasks:</emphasis> -->
</para></listitem>
</itemizedlist>
<para>
Please refer to the <emphasis>Hibernate Tools</emphasis> package and it's documentation
Please refer to the <emphasis>Hibernate Tools</emphasis> package documentation
for more information.
</para>
<para>
However, the Hibernate main package comes bundled with an integrated tool (it can even
be used from "inside" Hibernate on-the-fly): <emphasis>SchemaExport</emphasis> aka
<literal>hbm2ddl</literal>.
However, the Hibernate main package comes bundled with an integrated tool : <emphasis>SchemaExport</emphasis> aka
<literal>hbm2ddl</literal>.It can even
be used from "inside" Hibernate.
</para>
<sect1 id="toolsetguide-s1" revision="2">
<title>Automatic schema generation</title>
<para>
DDL may be generated from your mapping files by a Hibernate utility. The generated
schema includes referential integrity constraints (primary and foreign keys) for
DDL can be generated from your mapping files by a Hibernate utility. The generated
schema includes referential integrity constraints, primary and foreign keys, for
entity and collection tables. Tables and sequences are also created for mapped
identifier generators.
</para>
@ -88,11 +88,11 @@
<para>
You <emphasis>must</emphasis> specify a SQL <literal>Dialect</literal> via the
<literal>hibernate.dialect</literal> property when using this tool, as DDL
is highly vendor specific.
is highly vendor-specific.
</para>
<para>
First, customize your mapping files to improve the generated schema.
First, you must customize your mapping files to improve the generated schema. The next section covers schema customization.
</para>
<sect2 id="toolsetguide-s1-2" revision="3">
@ -100,7 +100,7 @@
<para>
Many Hibernate mapping elements define optional attributes named <literal>length</literal>,
<literal>precision</literal> and <literal>scale</literal>. You may set the length, precision
<literal>precision</literal> and <literal>scale</literal>. You can set the length, precision
and scale of a column with this attribute.
</para>
@ -109,9 +109,9 @@
<programlisting><![CDATA[<property name="balance" precision="12" scale="2"/>]]></programlisting>
<para>
Some tags also accept a <literal>not-null</literal> attribute (for generating a
<literal>NOT NULL</literal> constraint on table columns) and a <literal>unique</literal>
attribute (for generating <literal>UNIQUE</literal> constraint on table columns).
Some tags also accept a <literal>not-null</literal> attribute for generating a
<literal>NOT NULL</literal> constraint on table columns, and a <literal>unique</literal>
attribute for generating <literal>UNIQUE</literal> constraint on table columns.
</para>
<programlisting><![CDATA[<many-to-one name="bar" column="barId" not-null="true"/>]]></programlisting>
@ -119,10 +119,10 @@
<programlisting><![CDATA[<element column="serialNumber" type="long" not-null="true" unique="true"/>]]></programlisting>
<para>
A <literal>unique-key</literal> attribute may be used to group columns in
a single unique key constraint. Currently, the specified value of the
A <literal>unique-key</literal> attribute can be used to group columns in
a single, unique key constraint. Currently, the specified value of the
<literal>unique-key</literal> attribute is <emphasis>not</emphasis> used
to name the constraint in the generated DDL, only to group the columns in
to name the constraint in the generated DDL. It is only used to group the columns in
the mapping file.
</para>
@ -131,15 +131,15 @@
<para>
An <literal>index</literal> attribute specifies the name of an index that
will be created using the mapped column or columns. Multiple columns may be
grouped into the same index, simply by specifying the same index name.
will be created using the mapped column or columns. Multiple columns can be
grouped into the same index by simply specifying the same index name.
</para>
<programlisting><![CDATA[<property name="lastName" index="CustName"/>
<property name="firstName" index="CustName"/>]]></programlisting>
<para>
A <literal>foreign-key</literal> attribute may be used to override the name
A <literal>foreign-key</literal> attribute can be used to override the name
of any generated foreign key constraint.
</para>
@ -157,9 +157,9 @@
</property>]]></programlisting>
<para>
The <literal>default</literal> attribute lets you specify a default value for
a column (you should assign the same value to the mapped property before
saving a new instance of the mapped class).
The <literal>default</literal> attribute allows you to specify a default value for
a column.You should assign the same value to the mapped property before
saving a new instance of the mapped class.
</para>
<programlisting><![CDATA[<property name="credits" type="integer" insert="false">
@ -193,6 +193,8 @@
</class>]]></programlisting>
<para>The following table summarizes these optional attributes.</para>
<table frame="topbot" id="schemattributes-summary" revision="2">
<title>Summary</title>
<tgroup cols="3">
@ -225,7 +227,7 @@
<row>
<entry><literal>not-null</literal></entry>
<entry><literal>true|false</literal></entry>
<entry>specfies that the column should be non-nullable</entry>
<entry>specifies that the column should be non-nullable</entry>
</row>
<row>
<entry><literal>unique</literal></entry>
@ -299,7 +301,7 @@
<para>
This results in a <literal>comment on table</literal> or
<literal>comment on column</literal> statement in the generated
DDL (where supported).
DDL where supported.
</para>
</sect2>
@ -311,8 +313,10 @@
The <literal>SchemaExport</literal> tool writes a DDL script to standard out and/or
executes the DDL statements.
</para>
<para>
<para>The following table displays the <literal>SchemaExport</literal> command line options</para>
<para>
<literal>java -cp </literal><emphasis>hibernate_classpaths</emphasis>
<literal>org.hibernate.tool.hbm2ddl.SchemaExport</literal> <emphasis>options mapping_files</emphasis>
</para>
@ -331,7 +335,7 @@
<tbody>
<row>
<entry><literal>--quiet</literal></entry>
<entry>don't output the script to stdout</entry>
<entry>do not output the script to stdout</entry>
</row>
<row>
<entry><literal>--drop</literal></entry>
@ -343,7 +347,7 @@
</row>
<row>
<entry><literal>--text</literal></entry>
<entry>don't export to the database</entry>
<entry>do not export to the database</entry>
</row>
<row>
<entry><literal>--output=my_schema.ddl</literal></entry>
@ -374,7 +378,7 @@
</table>
<para>
You may even embed <literal>SchemaExport</literal> in your application:
You can even embed <literal>SchemaExport</literal> in your application:
</para>
<programlisting><![CDATA[Configuration cfg = ....;
@ -386,7 +390,7 @@ new SchemaExport(cfg).create(false, true);]]></programlisting>
<title>Properties</title>
<para>
Database properties may be specified
Database properties can be specified:
</para>
<itemizedlist spacing="compact">
@ -475,7 +479,7 @@ new SchemaExport(cfg).create(false, true);]]></programlisting>
<para>
The <literal>SchemaUpdate</literal> tool will update an existing schema with "incremental" changes.
Note that <literal>SchemaUpdate</literal> depends heavily upon the JDBC metadata API, so it will
The <literal>SchemaUpdate</literal> depends upon the JDBC metadata API and, as such, will
not work with all JDBC drivers.
</para>
@ -498,11 +502,11 @@ new SchemaExport(cfg).create(false, true);]]></programlisting>
<tbody>
<row>
<entry><literal>--quiet</literal></entry>
<entry>don't output the script to stdout</entry>
<entry>do not output the script to stdout</entry>
</row>
<row>
<entry><literal>--text</literal></entry>
<entry>don't export the script to the database</entry>
<entry>do not export the script to the database</entry>
</row>
<row>
<entry><literal>--naming=eg.MyNamingStrategy</literal></entry>
@ -521,7 +525,7 @@ new SchemaExport(cfg).create(false, true);]]></programlisting>
</table>
<para>
You may embed <literal>SchemaUpdate</literal> in your application:
You can embed <literal>SchemaUpdate</literal> in your application:
</para>
<programlisting><![CDATA[Configuration cfg = ....;
@ -557,15 +561,15 @@ new SchemaUpdate(cfg).execute(false);]]></programlisting>
<para>
The <literal>SchemaValidator</literal> tool will validate that the existing database schema "matches"
your mapping documents. Note that <literal>SchemaValidator</literal> depends heavily upon the JDBC
metadata API, so it will not work with all JDBC drivers. This tool is extremely useful for testing.
your mapping documents. The <literal>SchemaValidator</literal> depends heavily upon the JDBC
metadata API and, as such, will not work with all JDBC drivers. This tool is extremely useful for testing.
</para>
<para>
<literal>java -cp </literal><emphasis>hibernate_classpaths</emphasis>
<literal>org.hibernate.tool.hbm2ddl.SchemaValidator</literal> <emphasis>options mapping_files</emphasis>
</para>
<para>The following table displays the <literal>SchemaValidator</literal> command line options:
<table frame="topbot">
<title><literal>SchemaValidator</literal> Command Line Options</title>
<tgroup cols="2">
@ -595,7 +599,7 @@ new SchemaUpdate(cfg).execute(false);]]></programlisting>
</table>
<para>
You may embed <literal>SchemaValidator</literal> in your application:
You can embed <literal>SchemaValidator</literal> in your application:
</para>
<programlisting><![CDATA[Configuration cfg = ....;

View File

@ -29,17 +29,17 @@
<title>XML Mapping</title>
<para><emphasis>
Note that this is an experimental feature in Hibernate 3.0 and is under
extremely active development.
XML Mapping is an experimental feature in Hibernate 3.0 and is currently under
active development.
</emphasis></para>
<sect1 id="xml-intro" revision="1">
<title>Working with XML data</title>
<para>
Hibernate lets you work with persistent XML data in much the same way
Hibernate allows you to work with persistent XML data in much the same way
you work with persistent POJOs. A parsed XML tree can be thought of
as just another way to represent the relational data at the object level,
as another way of representing the relational data at the object level,
instead of POJOs.
</para>
@ -59,9 +59,9 @@
</para>
<para>
A single mapping may be used to simultaneously map properties of a class
A single mapping can be used to simultaneously map properties of a class
and nodes of an XML document to the database, or, if there is no class to map,
it may be used to map just the XML.
it can be used to map just the XML.
</para>
<sect2 id="xml-intro-mapping">
@ -126,8 +126,8 @@
<para>
This mapping allows you to access the data as a dom4j tree, or as a graph of
property name/value pairs (java <literal>Map</literal>s). The property names
are purely logical constructs that may be referred to in HQL queries.
property name/value pairs or java <literal>Map</literal>s. The property names
are purely logical constructs that can be referred to in HQL queries.
</para>
</sect2>
@ -138,25 +138,25 @@
<title>XML mapping metadata</title>
<para>
Many Hibernate mapping elements accept the <literal>node</literal> attribute.
This let's you specify the name of an XML attribute or element that holds the
A range of Hibernate mapping elements accept the <literal>node</literal> attribute.
This lets you specify the name of an XML attribute or element that holds the
property or entity data. The format of the <literal>node</literal> attribute
must be one of the following:
</para>
<itemizedlist spacing="compact">
<listitem>
<para><literal>"element-name"</literal> - map to the named XML element</para>
<para><literal>"element-name"</literal>: map to the named XML element</para>
</listitem>
<listitem>
<para><literal>"@attribute-name"</literal> - map to the named XML attribute</para>
<para><literal>"@attribute-name"</literal>: map to the named XML attribute</para>
</listitem>
<listitem>
<para><literal>"."</literal> - map to the parent element</para>
<para><literal>"."</literal>: map to the parent element</para>
</listitem>
<listitem>
<para>
<literal>"element-name/@attribute-name"</literal> -
<literal>"element-name/@attribute-name"</literal>:
map to the named attribute of the named element
</para>
</listitem>
@ -169,12 +169,12 @@
will be embedded directly in the XML tree for the entity that owns the association.
Otherwise, if <literal>embed-xml="false"</literal>, then only the referenced
identifier value will appear in the XML for single point associations and
collections will simply not appear at all.
collections will not appear at all.
</para>
<para>
You should be careful not to leave <literal>embed-xml="true"</literal> for
too many associations, since XML does not deal well with circularity!
Do not leave <literal>embed-xml="true"</literal> for
too many associations, since XML does not deal well with circularity.
</para>
<programlisting><![CDATA[<class name="Customer"
@ -213,14 +213,14 @@
</class>]]></programlisting>
<para>
in this case, we have decided to embed the collection of account ids, but not
In this case, the collection of account ids is embedded, but not
the actual account data. The following HQL query:
</para>
<programlisting><![CDATA[from Customer c left join fetch c.accounts where c.lastName like :lastName]]></programlisting>
<para>
Would return datasets such as this:
would return datasets such as this:
</para>
<programlisting><![CDATA[<customer id="123456789">
@ -263,7 +263,7 @@
<title>Manipulating XML data</title>
<para>
Let's rearead and update XML documents in the application. We do this by
You can also re-read and update XML documents in the application. You can do this by
obtaining a dom4j session:
</para>
@ -303,8 +303,8 @@ tx.commit();
session.close();]]></programlisting>
<para>
It is extremely useful to combine this feature with Hibernate's <literal>replicate()</literal>
operation to implement XML-based data import/export.
When implementing XML-based data import/export, it is useful to combine this feature with Hibernate's <literal>replicate()</literal>
operation.
</para>
</sect1>