mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-22 19:15:15 +00:00
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:
parent
4167921ea3
commit
4bd552cfdb
@ -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>
|
||||
|
@ -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><key></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><key></literal> element of the collection mapping.
|
||||
Do not only
|
||||
declare <literal>not-null="true"</literal> on a possible nested
|
||||
<literal><column></literal> element, but on the <literal><key></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>
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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();
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
<variablelist spacing="compact">
|
||||
<varlistentry>
|
||||
<term>Write fine-grained classes and map them using <literal><component></literal>.</term>
|
||||
<term>Write fine-grained classes and map them using <literal><component></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
|
||||
|
@ -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><set></literal>
|
||||
the type of interface. For example, a <literal><set></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><key></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><map-key></literal>, it may be an entity reference mapped with
|
||||
<literal><map-key-many-to-many></literal>, or it may be a composite type,
|
||||
<literal><map-key></literal>. It can be an entity reference mapped with
|
||||
<literal><map-key-many-to-many></literal>, or it can be a composite type
|
||||
mapped with <literal><composite-map-key></literal>. The index of an array or
|
||||
list is always of type <literal>integer</literal> and is mapped using the
|
||||
<literal><list-index></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><bag></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><bag></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><element></literal> tag.
|
||||
For a collection of values use the <literal><element></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><many-to-many></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><one-to-many></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><one-to-many></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><one-to-many></literal> element does not need to
|
||||
The <literal><one-to-many></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><one-to-many></literal> association is declared <literal>NOT NULL</literal>,
|
||||
you must declare the <literal><key></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><list></literal>
|
||||
or <literal><map></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><map></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 <idbag></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><idbag></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><idbag></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><idbag></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><idbag></literal> is
|
||||
<emphasis>much</emphasis> better than a regular <literal><bag></literal>!
|
||||
The update performance of an <literal><idbag></literal> supersedes a regular <literal><bag></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><key></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>
|
||||
|
||||
|
@ -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><element></literal> tag with a
|
||||
<literal><composite-element></literal> tag.
|
||||
<literal><composite-element></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><nested-composite-element></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><set></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><set></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><list></literal>, <literal><map></literal>,
|
||||
@ -210,10 +211,10 @@
|
||||
|
||||
<para>
|
||||
A special case of a composite element is a composite element with a nested
|
||||
<literal><many-to-one></literal> element. A mapping like this allows
|
||||
<literal><many-to-one></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><composite-map-key></literal> element lets you map a
|
||||
component class as the key of a <literal>Map</literal>. Make sure you override
|
||||
The <literal><composite-map-key></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><composite-id></literal> tag (with nested
|
||||
<literal><key-property></literal> elements) in place of the usual
|
||||
Use the <literal><composite-id></literal> tag, with nested
|
||||
<literal><key-property></literal> elements, in place of the usual
|
||||
<literal><id></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><column></literal> tag is an alternative to the
|
||||
<literal>column</literal> attribute everywhere.)
|
||||
<note>
|
||||
</title>
|
||||
Note
|
||||
</title>
|
||||
<para>
|
||||
The <literal><column></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><one-to-many></literal> element, as usual, declares no columns.)
|
||||
The <literal><one-to-many></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><dynamic-component></literal> mapping are identical
|
||||
to <literal><component></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>
|
||||
|
||||
|
@ -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><property></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><cache></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>
|
||||
|
@ -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><listener/></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><listener type="..." class="..."/></literal> is just a shorthand
|
||||
Note that <literal><listener type="..." class="..."/></literal> is shorthand
|
||||
for <literal><event type="..."><listener class="..."/></event></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"/>
|
||||
|
@ -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>
|
||||
|
@ -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><one-to-many></literal> association from <literal>Parent</literal>
|
||||
to <literal>Child</literal>. (The alternative approach is to declare the <literal>Child</literal> as a
|
||||
<literal><composite-element></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><composite-element></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><composite-element></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><composite-element></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>
|
||||
|
@ -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;
|
||||
|
@ -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><filter-def/></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><filter-def/></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>
|
||||
|
||||
|
@ -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><subclass></literal>,
|
||||
and <literal><joined-subclass></literal> and
|
||||
<literal><joined-subclass></literal> and
|
||||
<literal><union-subclass></literal> mappings under the same root
|
||||
<literal><class></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><class></literal> element, by combining the
|
||||
<literal><subclass></literal> and <literal><join></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><subclass></literal> and
|
||||
<literal><join></literal>, as follow:
|
||||
can combine the use of <literal><subclass></literal> and
|
||||
<literal><join></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><union-subclass></literal>.
|
||||
There are two ways we can map the table per concrete class
|
||||
strategy. First, you can use <literal><union-subclass></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>[ <!ENTITY allproperties SYSTEM "allproperties.xml"> ]</literal>
|
||||
in the <literal>DOCTYPE</literal> declartion and
|
||||
(for example, <literal>[ <!ENTITY allproperties SYSTEM "allproperties.xml"> ]</literal>
|
||||
in the <literal>DOCTYPE</literal> declaration and
|
||||
<literal>&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><class></literal> element (and since
|
||||
Since the subclasses
|
||||
are each mapped in their own <literal><class></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><union-subclass></literal>
|
||||
mappings.
|
||||
|
@ -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><class-cache></literal> and
|
||||
Alternatively, you can specify <literal><class-cache></literal> and
|
||||
<literal><collection-cache></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><key></literal> and <literal><index></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><key></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><set></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><set></literal>, you must declare all columns
|
||||
as <literal>not-null="true"</literal>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<literal><idbag></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>.
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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><natural-id></literal>, and enable use of the second-level cache.
|
||||
First, map the natural key of your entity using
|
||||
<literal><natural-id></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>
|
||||
|
||||
|
@ -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><any></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><any></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>=, >=, <=, <>, !=, like</literal>
|
||||
binary comparison operators: <literal>=, >=, <=, <>, !=, 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 & 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>
|
||||
|
||||
|
@ -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><return-join></literal> and
|
||||
<literal><load-collection></literal> elements are used to join
|
||||
associations and define queries which initialize collections,
|
||||
respectively.</para>
|
||||
<para>The <literal><return-join></literal> element is use to join associations and
|
||||
the <literal><load-collection></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><resultset></literal> element to either reuse them across
|
||||
<para>You can externalize the resultset mapping information in a
|
||||
<literal><resultset></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><return-property></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><return-property></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><return-property></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><return-property></literal> in combination with the
|
||||
<literal>{}</literal>-syntax for injection. Allowing users to choose how
|
||||
<para>In this example
|
||||
<literal><return-property></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><return-join></literal> and
|
||||
<literal><load-collection></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(<parameters>) }</literal> or <literal>{ ? = call
|
||||
procedureName(<parameters>}</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">
|
||||
|
@ -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><hibernate-mapping></literal>
|
||||
element requires a global unique name for the query, while a query declaration inside a
|
||||
<literal><class></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><version></literal> or
|
||||
<literal><timestamp></literal>), and the version property value
|
||||
if the object is versioned by a <literal><version></literal> or
|
||||
<literal><timestamp></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><many-to-one></literal>
|
||||
It does not usually make sense to enable cascade on a <literal><many-to-one></literal>
|
||||
or <literal><many-to-many></literal> association. Cascade is often useful for
|
||||
<literal><one-to-one></literal> and <literal><one-to-many></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><one-to-many></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>
|
||||
|
||||
|
@ -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 = ....;
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user