First batch of doco updates

git-svn-id: https://svn.jboss.org/repos/hibernate/trunk/Hibernate3/doc@4363 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Christian Bauer 2004-08-17 10:42:31 +00:00
parent 35f519e011
commit 7225b36735
3 changed files with 171 additions and 120 deletions

View File

@ -2,7 +2,7 @@
<title>Architecture</title>
<sect1 id="architecture-overview">
<sect1 id="architecture-overview" revision="1">
<title>Overview</title>
<para>
@ -113,7 +113,9 @@
(Optional) A single-threaded, short-lived object used by the application to
specify atomic units of work. Abstracts application from underlying JDBC,
JTA or CORBA transaction. A <literal>Session</literal> might span several
<literal>Transaction</literal>s in some cases.
<literal>Transaction</literal>s in some cases. However, transaction demarcation,
either using the underlying API or <literal>Transaction</literal>, is never
optional!
</para>
</listitem>
</varlistentry>
@ -136,6 +138,15 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><emphasis>Extension Interfaces</emphasis></term>
<listitem>
<para>
Hibernate offers many optional extension interfaces you can implement to customize
the behavior of your persistence layer. See the API documentation for details.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
@ -146,8 +157,9 @@
</para>
</sect1>
<sect1 id="architecture-jmx">
<sect1 id="architecture-jmx" revision="1">
<title>JMX Integration</title>
<para>
JMX is the J2EE standard for management of Java components. Hibernate may be managed via
a JMX standard MBean but because most application servers do not yet support JMX, Hibernate
@ -156,7 +168,13 @@
<para>
Please see the Hibernate website for more information on how to configure Hibernate to
run as a JMX component inside JBoss.
run as a JMX component inside JBoss. Integration with other JMX containers is also
possible.
</para>
<!-- TODO: More documentation about JMX integration. -->
<para>
TODO: More documentation about JMX integration.
</para>
</sect1>
@ -166,6 +184,11 @@
Hibernate may also be configured as a JCA connector. Please see the website for more
details.
</para>
<!-- TODO: More documentation about JCA integration. -->
<para>
TODO: More documentation about JCA integration.
</para>
</sect1>
</chapter>

View File

@ -1,17 +1,18 @@
<chapter id="session-configuration">
<chapter id="session-configuration" revision="1">
<title>SessionFactory Configuration</title>
<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
default values and Hibernate is distributed with an example
<literal>hibernate.properties</literal> file that shows the various options.
You usually only have to put that file in your classpath and customize it.
<literal>hibernate.properties</literal> file in <literal>etc/</literal> that shows
the various options. You usually only have to put that file in your classpath
and customize it.
</para>
<sect1 id="configuration-programmatic">
<title>Programmatic Configuration</title>
<sect1 id="configuration-programmatic" revision="1">
<title>Programmatic configuration</title>
<para>
An instance of <literal>org.hibernate.cfg.Configuration</literal>
@ -24,7 +25,7 @@
<para>
You may obtain a <literal>Configuration</literal> instance by
instantiating it directly. Heres an example of setting up a datastore from
mappings defined in two XML configuration files (in the classpath):
mappings defined in two XML mapping files (in the classpath):
</para>
<programlisting><![CDATA[Configuration cfg = new Configuration()
@ -59,10 +60,16 @@ Configuration cfg = new Configuration()
.setProperties(props);]]></programlisting>
<para>
A <literal>Configuration</literal> is intended as a configuration-time object, to be
A <literal>Configuration</literal> is intended as a startup-time object, to be
discarded once a <literal>SessionFactory</literal> is built.
</para>
<para>
Instead of adding mapping files and setting properties programatially, you may
also place Hibernate configuration files in your classpath, as you will see
later.
</para>
</sect1>
<sect1 id="configuration-sessionfactory">
@ -83,7 +90,7 @@ Configuration cfg = new Configuration()
</sect1>
<sect1 id="configuration-userjdbc">
<sect1 id="configuration-userjdbc" revision="1">
<title>User provided JDBC connection</title>
<para>
@ -102,10 +109,16 @@ Session session = sessions.openSession(conn);
<literal>Session</literal>s on the same JDBC connection!
</para>
<para>
We don't recommend user-provided JDBC connections, as Hibernate will disable
caching (it doesn't know what else you might have executed on the given connection)
and one of the following options is usually more appropriate.
</para>
</sect1>
<sect1 id="configuration-hibernatejdbc">
<sect1 id="configuration-hibernatejdbc" revision="1">
<title>Hibernate provided JDBC connection</title>
<para>
@ -217,25 +230,20 @@ Session session = sessions.openSession(conn);
</table>
<para>
Hibernate's own connection pooling algorithm is quite rudimentary. It is intended
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. Use a third party pool for best performance and stability,
i.e., replace the <literal>hibernate.connection.pool_size</literal> property with
connection pool specific settings.
connection pool specific settings. This will turn off Hibernate's internal pool.
</para>
<para>
C3P0 is an open source JDBC connection pool distributed along with
Hibernate in the <literal>lib</literal> directory. Hibernate will use the built-in
Hibernate in the <literal>lib</literal> directory. Hibernate will use its
<literal>C3P0ConnectionProvider</literal> for connection pooling if you set
the <literal>hibernate.c3p0.*</literal> properties.
There is also built-in support for Apache DBCP and for Proxool. You must set the
properties <literal>hibernate.dbcp.*</literal> (DBCP connection pool properties)
to enable the <literal>DBCPConnectionProvider</literal>. Prepared statement caching is
enabled (highly recommend) if <literal>hibernate.dbcp.ps.*</literal>
(DBCP statement cache properties) are set. Please refer the the Apache commons-pool
documentation for the interpretation of these properties. You should set the
<literal>hibernate.proxool.*</literal> properties if you wish to use Proxool.
<literal>hibernate.c3p0.*</literal> properties. If you'd like to use Proxool
refer to the packaged <literal>hibernate.properties</literal> and the Hibernate
web site for more information.
</para>
<para>
@ -345,7 +353,7 @@ hibernate.dialect = \
</sect1>
<sect1 id="configuration-optional">
<sect1 id="configuration-optional" revision="1">
<title>Optional configuration properties</title>
<para>
@ -356,10 +364,11 @@ hibernate.dialect = \
<para>
System-level properties can only be set via <literal>java -Dproperty=value</literal> or
be defined in <literal>hibernate.properties</literal> and not with an instance of
<literal>Properties</literal> passed to the <literal>Configuration</literal>.
<literal>Properties</literal> passed to the <literal>Configuration</literal>. They
are also not available in the <literal>hibernate.cfg.xml</literal> file, discusse later.
</para>
<table frame="topbot" id="configuration-optional-properties" revision="3">
<table frame="topbot" id="configuration-optional-properties" revision="4">
<title>Hibernate Configuration Properties</title>
<tgroup cols="2">
<colspec colname="c1" colwidth="1*"/>
@ -410,18 +419,6 @@ hibernate.dialect = \
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.use_outer_join</literal>
</entry>
<entry>
Enables outer join fetching. Deprecated, use <literal>max_fetch_depth</literal>.
<para>
<emphasis role="strong">eg.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.max_fetch_depth</literal>
@ -719,6 +716,22 @@ hibernate.dialect = \
</para>
</entry>
</row>
<row>
<entry>
<literal>hibernate.generate_statistics</literal>
</entry>
<entry>
If turned on, several runtime statistics are available by calling
<literal>SessionFactory.getStatistics()</literal>. Also see the
<literal>StatisticsServiceMBean</literal> if you are using a
JMX server, documented on the Hibernate web site.
<para>
<emphasis role="strong">eg.</emphasis>
<literal>true</literal> | <literal>false</literal>
</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
@ -814,7 +827,7 @@ hibernate.dialect = \
</sect2>
<sect2 id="configuration-optional-outerjoin">
<sect2 id="configuration-optional-outerjoin" revision="1">
<title>Outer Join Fetching</title>
<para>
@ -828,7 +841,10 @@ hibernate.dialect = \
<para>
By default, the fetched graph when loading an objects ends at leaf objects,
collections, objects with proxies, or where circularities occur.
collections, objects with proxies, or where circularities occur in the case
of *-to-one associations. Hibernate will however execute an immediate additional
<literal>SELECT</literal> for any persistent collection (we recommend that you
turn on lazy loading for all collection mappings).
</para>
<para>
@ -845,12 +861,13 @@ hibernate.dialect = \
to <literal>auto</literal> outer join. However, one-to-many associations and
collections are never fetched with an outer-join, unless explicitely declared
for each particular association. This behavior can also be overriden at runtime
with Hibernate queries.
with Hibernate queries. See the query chapters in the documentation for more
details.
</para>
</sect2>
<sect2 id="configuration-optional-binarystreams">
<sect2 id="configuration-optional-binarystreams" revision="1">
<title>Binary Streams</title>
<para>
@ -858,28 +875,30 @@ hibernate.dialect = \
be passed to/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 JVM-level setting only.</emphasis>
<emphasis>This is a system-level setting only.</emphasis>
</para>
</sect2>
<sect2 id="configuration-optional-cacheprovider">
<sect2 id="configuration-optional-cacheprovider" revision="1">
<title>Custom <literal>CacheProvider</literal></title>
<para>
You may integrate a JVM-level (or clustered) second-level cache system by
implementing the interface <literal>org.hibernate.cache.CacheProvider</literal>.
You may select the custom implementation by setting
<literal>hibernate.cache.provider_class</literal>.
<literal>hibernate.cache.provider_class</literal>. See the "Performance" chapter
for more details.
</para>
</sect2>
<sect2 id="configuration-optional-transactionstrategy">
<sect2 id="configuration-optional-transactionstrategy" revision="1">
<title>Transaction strategy configuration</title>
<para>
If you wish to use the Hibernate <literal>Transaction</literal> API, you must
If you wish to use the Hibernate <literal>Transaction</literal> API instead
of directly calling a particular transaction API, you must
specify a factory class for <literal>Transaction</literal> instances by
setting the property <literal>hibernate.transaction.factory_class</literal>.
The <literal>Transaction</literal> API hides the underlying transaction
@ -971,17 +990,18 @@ hibernate.dialect = \
</sect2>
<sect2 id="configuration-optional-jndi">
<sect2 id="configuration-optional-jndi" revision="1">
<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.
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> in a managed environment.
</para>
<para>
If you wish to have the <literal>SessionFactory</literal> bound to a JNDI namespace, specify
a name (eg. <literal>java:comp/env/hibernate/SessionFactory</literal>) using the property
a name (eg. <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, eg. Tomcat.)
@ -995,8 +1015,16 @@ hibernate.dialect = \
</para>
<para>
If you do choose to use JNDI, an EJB or other utility class may obtain the
<literal>SessionFactory</literal> using a JNDI lookup.
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.
</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. Note that this
setup is not neccessary if you use the <literal>HibernateUtil</literal> helper class
introduced in chapter 1, which acts as a Singleton registry.
</para>
</sect2>
@ -1089,14 +1117,14 @@ hibernate.dialect = \
</sect1>
<sect1 id="configuration-xmlconfig">
<sect1 id="configuration-xmlconfig" revision="1">
<title>XML Configuration File</title>
<para>
An alternative approach is to specify a full configuration in a file named
<literal>hibernate.cfg.xml</literal>. This file can be used as a replacement
for the <literal>hibernate.properties</literal> file or, if both are present,
override properties.
An alternative approach to configuration is to specify a full configuration in
a file named <literal>hibernate.cfg.xml</literal>. This file can be used as a
replacement for the <literal>hibernate.properties</literal> file or, if both
are present, override properties.
</para>
<para>
@ -1113,13 +1141,12 @@ hibernate.dialect = \
<!-- a SessionFactory instance listed as /jndi/name -->
<session-factory
name="java:comp/env/hibernate/SessionFactory">
name="java:hibernate/SessionFactory">
<!-- properties -->
<property name="connection.datasource">my/first/datasource</property>
<property name="connection.datasource">java:/comp/env/jdbc/MyDB</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">false</property>
<property name="use_outer_join">true</property>
<property name="transaction.factory_class">
org.hibernate.transaction.JTATransactionFactory
</property>
@ -1133,6 +1160,12 @@ hibernate.dialect = \
</hibernate-configuration>]]></programlisting>
<para>
As you can see, 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.
</para>
<para>
Configuring Hibernate is then as simple as
</para>

View File

@ -1,15 +1,15 @@
<chapter id="quickstart">
<title>Quickstart with Tomcat</title>
<sect1 id="quickstart-intro">
<sect1 id="quickstart-intro" revision="1">
<title>Getting started with Hibernate</title>
<para>
This tutorial explains a setup of Hibernate 2.1 with the Apache Tomcat
This tutorial explains a setup of Hibernate 3.0 with the Apache Tomcat
servlet container for a web-based application. Hibernate works
well in a managed environment with all major J2EE application servers, or
even in standalone Java applications. The database system used in this
tutorial is PostgreSQL 7.3, support for other database is only a matter
tutorial is PostgreSQL 7.4, support for other database is only a matter
of changing the Hibernate SQL dialect configuration.
</para>
@ -35,7 +35,7 @@
Hibernate uses JDBC connections to execute SQL on the database, so you
either have to provide pooled JDBC connections or configure Hibernate to
use one of the directly supported pools (C3P0, Proxool). For this tutorial,
copy the <literal>pg73jdbc3.jar</literal> library (for PostgreSQL 7.3 and JDK 1.4)
copy the <literal>pg74jdbc3.jar</literal> library (for PostgreSQL 7.4 and JDK 1.4)
to the global classloaders path. If you'd like to use a different database, simply
copy its appropriate JDBC driver.
</para>
@ -52,7 +52,7 @@
</listitem>
<listitem>
<para>
Hibernate is packaged as a JAR library. The <literal>hibernate2.jar</literal>
Hibernate is packaged as a JAR library. The <literal>hibernate3.jar</literal>
file should be copied in the context classpath together with other classes of
the application. Hibernate requires some 3rd party libraries at runtime, these
come bundled with the Hibernate distribution in the <literal>lib/</literal>
@ -107,17 +107,6 @@
Commons project.
</entry>
</row>
<row>
<entry>
ODMG4 (required)
</entry>
<entry>
Hibernate provides an optional ODMG compliant persistence manager
interface. It is required if you like to map collections, even
if you don't intend to use the ODMG API. We don't map collections
in this tutorial, but it's a good idea to copy the JAR anyway.
</entry>
</row>
<row>
<entry>
EHCache (required)
@ -213,12 +202,11 @@
any servlets, call the path <literal>http://localhost:8080/quickstart</literal>
in your browser (of course, adding the name of the servlet as mapped in your
<literal>web.xml</literal>). You may also go ahead and create a simple servlet
now that has an empty <literal>process()</literal>
now that has an empty <literal>process()</literal> method.
</para>
<para>
Tomcat uses the DBCP connection pool with this configuration and provides pooled
JDBC <literal>Connection</literal>s through JNDI at
Tomcat provides connections now through JNDI at
<literal>java:comp/env/jdbc/quickstart</literal>. If you have trouble getting the
connection pool running, refer to the Tomcat documentation. If you get JDBC driver
exception messages, try to setup JDBC connection pool without Hibernate first.
@ -226,11 +214,11 @@
</para>
<para>
The next step is to configure Hibernate, using the connections from the JNDI bound pool.
We use Hibernates XML based configuration. The basic approach, using properties, is
equivalent in features, but doesn't offer any advantages. We use the XML configuration
because it is usually more convenient. The XML configuration file is placed in the
context classpath (<literal>WEB-INF/classes</literal>), as
Your next step is to configure Hibernate. Hibernate has to know how it should obtain
JDBC connections We use Hibernates XML-based configuration. The other approach, using
a properties file, is equivalent in features, but doesn't offer any advantages. We use
the XML configuration because it is usually more convenient. The XML configuration file
is placed in the context classpath (<literal>WEB-INF/classes</literal>), as
<literal>hibernate.cfg.xml</literal>:
</para>
@ -257,7 +245,7 @@
<para>
We turn logging of SQL commands off and tell Hibernate what database SQL
dialect is used and where to get the JDBC connections (by declaring the JNDI
address of the Tomcat bound datasource pool). The dialect is a required setting,
address of the Tomcat bound pool). The dialect is a required setting,
databases differ in their interpretation of the SQL "standard". Hibernate will take
care of the differences and comes bundled with dialects for all major
commercial and open source databases.
@ -274,14 +262,14 @@
The last element of the <literal>hibernate.cfg.xml</literal> declares
<literal>Cat.hbm.xml</literal> as the name of a Hibernate XML mapping
file for the persistent class <literal>Cat</literal>. This file contains
the metadata for the mapping of the POJO class to a datbase table (or multiple
tables). We'll come back to that file soon. Let's write the POJO class first
and then declare the mapping metadata for it.
the metadata for the mapping of the POJO class <literal>Cat</literal> to
a datbase table (or tables). We'll come back to that file soon. Let's write
the POJO class first and then declare the mapping metadata for it.
</para>
</sect1>
<sect1 id="quickstart-persistentclass">
<sect1 id="quickstart-persistentclass" revision="1">
<title>First persistent class</title>
<para>
@ -289,7 +277,7 @@
called Plain Ordinary Java Objects) programming model for persistent classes.
A POJO is much like a JavaBean, with properties of the class accessible via getter
and setter methods, shielding the internal representation from the publicly
visible interface:
visible interface (Hibernate can also access fields directly, if needed):
</para>
<programlisting><![CDATA[package org.hibernate.examples.quickstart;
@ -351,16 +339,16 @@ public class Cat {
</para>
<para>
No special interface has to be implemented for persistent classes nor do we have
to subclass from a special root persistent class. Hibernate also doesn't use any
build time processing, such as byte-code manipulation, it relies solely on
No special interface has to be implemented for persistent classes nor do you have
to subclass from a special root persistent class. Hibernate also doesn't require
any build time processing, such as byte-code manipulation, it relies solely on
Java reflection and runtime class enhancement (through CGLIB). So, without any
dependency in the POJO class on Hibernate, we can map it to a database table.
dependency of the POJO class on Hibernate, we can map it to a database table.
</para>
</sect1>
<sect1 id="quickstart-mapping">
<sect1 id="quickstart-mapping" revision="1">
<title>Mapping the cat</title>
<para>
@ -400,7 +388,7 @@ public class Cat {
<para>
Every persistent class should have an identifer attribute (actually, only
classes representing entities, not dependent value objects, which
classes representing entities, not dependent value-typed classes, which
are mapped as components of an entity). This property is used to distinguish
persistent objects: Two cats are equal if
<literal>catA.getId().equals(catB.getId())</literal> is true, this concept is
@ -435,29 +423,29 @@ Indexes: cat_pkey primary key btree (cat_id)]]></programlisting>
<para>
You should now create this table in your database manually, and later read
<xref linkend="toolsetguide"/> if you want to automate this step with the
SchemaExport tool. This tool can create a full SQL DDL, including table
definition, custom column type constraints, unique constraints and indexes.
<literal>hbm2ddl</literal> tool. This tool can create a full SQL DDL, including
table definition, custom column type constraints, unique constraints and indexes.
</para>
</sect1>
<sect1 id="quickstart-playingwithcats" revision="1">
<sect1 id="quickstart-playingwithcats" revision="2">
<title>Playing with cats</title>
<para>
We're now ready to start Hibernate's <literal>Session</literal>. It is the
<emphasis>persistence manager</emphasis>interface, we use it
to store and retrieve <literal>Cat</literal>s to and from the database.
But first, we've to get a <literal>Session</literal> (Hibernate's unit-of-work)
from the <literal>SessionFactory</literal>:
<emphasis>persistence manager</emphasis>, we use it to store and retrieve
<literal>Cat</literal>s to and from the database. But first, we've to get a
<literal>Session</literal> (Hibernate's unit-of-work) from the
<literal>SessionFactory</literal>:
</para>
<programlisting><![CDATA[SessionFactory sessionFactory =
new Configuration().configure().buildSessionFactory();]]></programlisting>
<para>
A <literal>SessionFactory</literal> is responsible for one database and
may only use one XML configuration file (<literal>hibernate.cfg.xml</literal>).
The call to <literal>configure()</literal> loads the <literal>hibernate.cfg.xml</literal>
configuration file and initializes the <literal>Configuration</literal> instance.
You can set other properties (and even change the mapping metadata) by
accessing the <literal>Configuration</literal> <emphasis>before</emphasis>
you build the <literal>SessionFactory</literal> (it is immutable). Where
@ -472,7 +460,7 @@ Indexes: cat_pkey primary key btree (cat_id)]]></programlisting>
servlets, but in some other location. Furthermore, we need some kind of
<emphasis>Singleton</emphasis>, so we can access the
<literal>SessionFactory</literal> easily in application code. The approach
shown next solves both problems: configuration and easy access to a
shown next solves both problems: startup configuration and easy access to a
<literal>SessionFactory</literal>.
</para>
@ -494,6 +482,7 @@ public class HibernateUtil {
// Create the SessionFactory
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
log.error("Initial SessionFactory creation failed.", ex);
throw new ExceptionInInitializerError(ex);
}
@ -521,10 +510,11 @@ public class HibernateUtil {
<para>
This class does not only take care of the <literal>SessionFactory</literal>
with its static attribute, but also has a <literal>ThreadLocal</literal> to
hold the <literal>Session</literal> for the current executing thread. Make
sure you understand the Java concept of a thread-local variable before you
try to use this helper.
with its static initializer, but also has a <literal>ThreadLocal</literal>
variable which holds the <literal>Session</literal> for the current thread.
Make sure you understand the Java concept of a thread-local variable before you
try to use this helper. A more complex and powerful <literal>HibernateUtil</literal>
class can be found in <literal>CaveatEmptor</literal>, http://caveatemptor.hibernate.org/
</para>
<para>
@ -532,7 +522,8 @@ public class HibernateUtil {
it concurrently and request <literal>Session</literal>s. A <literal>Session</literal>
is a non-threadsafe object that represents a single unit-of-work with the database.
<literal>Session</literal>s are opened by a <literal>SessionFactory</literal> and
are closed when all work is completed:
are closed when all work is completed. An example in your servlet's
<literal>process()</literal> method might look like this (sans exception handling):
</para>
<programlisting><![CDATA[Session session = HibernateUtil.currentSession();
@ -555,17 +546,17 @@ HibernateUtil.closeSession();]]></programlisting>
We use Hibernates <literal>Transaction</literal> API to abstract from the underlying
transaction strategy (in our case, JDBC transactions). This allows our code
to be deployed with container-managed transactions (using JTA) without any changes.
Please note that the example above does not handle any exceptions.
</para>
<para>
Also note that you may call <literal>HibernateUtil.currentSession();</literal>
Note that you may call <literal>HibernateUtil.currentSession();</literal>
as many times as you like, you will always get the current <literal>Session</literal>
of this thread. You have to make sure the <literal>Session</literal> is closed
after your unit-of-work completes, either in your servlet code or in a servlet filter
before the HTTP response is send. The nice side effect of the latter is easy
before the HTTP response is send. The nice side effect of the second option is easy
lazy initialization: the <literal>Session</literal> is still open when the view is
rendered, so Hibernate can load unitialized objects while you navigate the graph.
rendered, so Hibernate can load unitialized objects while you navigate the current
object graph.
</para>
<para>
@ -595,7 +586,7 @@ tx.commit();]]></programlisting>
</sect1>
<sect1 id="quickstart-summary">
<sect1 id="quickstart-summary" revision="1">
<title>Finally</title>
<para>
@ -610,6 +601,10 @@ tx.commit();]]></programlisting>
Make sure you understand the implications of this design.
</para>
<para>
For a more complex application design, see http://caveatemptor.hibernate.org/
</para>
</sect1>
</chapter>