Many small improvements

git-svn-id: https://svn.jboss.org/repos/hibernate/trunk/Hibernate3/doc@5364 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Christian Bauer 2005-01-27 13:34:18 +00:00
parent a8b37ee2f2
commit 7ca1999a26
4 changed files with 228 additions and 120 deletions

View File

@ -250,6 +250,11 @@
<para>
Consult the JBoss AS user guide for more information about these options.
</para>
<para>
Another feature available as a JMX service are runtime Hibernate statistics. See
<xref linkend="configuration-optional-statistics"/>.
</para>
</sect1>
<sect1 id="architecture-jca" revision="1">

View File

@ -1,14 +1,14 @@
<chapter id="mapping">
<title>Basic O/R Mapping</title>
<sect1 id="mapping-declaration">
<sect1 id="mapping-declaration" revision="1">
<title>Mapping declaration</title>
<para>
Object/relational mappings are defined in an XML document. The mapping document
is designed to be readable and hand-editable. The mapping language is Java-centric,
meaning that mappings are constructed around persistent class declarations, not
table declarations.
Object/relational mappings are usually defined in an XML document. The mapping
document is designed to be readable and hand-editable. The mapping language is
Java-centric, meaning that mappings are constructed around persistent class
declarations, not table declarations.
</para>
<para>
@ -96,18 +96,20 @@
<sect2 id="mapping-declaration-doctype" revision="1">
<sect2 id="mapping-declaration-doctype" revision="2">
<title>Doctype</title>
<para>
All XML mappings should declare the doctype shown. The actual DTD may be found
at the URL above, in the directory <literal>hibernate-x.x.x/src/org/hibernate
</literal> or in <literal>hibernate3.jar</literal>. Hibernate will always look for
the DTD in its classpath first.
the DTD in its classpath first. If you experience lookups of the DTD using an
Internet connection, check your DTD declaration against the contents of your
claspath.
</para>
</sect2>
<sect2 id="mapping-declaration-mapping" revision="2">
<sect2 id="mapping-declaration-mapping" revision="3">
<title>hibernate-mapping</title>
<para>
@ -193,6 +195,16 @@
to assign two classes to the same "imported" name.
</para>
<para>
Note that the <literal>hibernate-mapping</literal> element allows you to nest
several persistent <literal>&lt;class&gt;</literal> mappings, as shown above.
It is however good practice (and expected by some tools) to map only a single
persistent class (or a single class hierarchy) in one mapping file and name
it after the persistent superclass, e.g. <literal>Cat.hbm.xml</literal>,
<literal>Dog.hbm.xml</literal>, or if using inheritance,
<literal>Animal.hbm.xml</literal>.
</para>
</sect2>
<sect2 id="mapping-declaration-class" revision="3">
@ -510,9 +522,9 @@
...]]></programlisting>
<para>
Declare the tables to synchronize this entity, to ensure that auto-flush happens
Declare the tables to synchronize this entity with, ensuring that auto-flush happens
correctly, and that queries against the derived entity do not return stale data.
The <literal>&lt;subselect&gt;</literal> is available as both an attribute and
The <literal>&lt;subselect&gt;</literal> is available as both as an attribute and
a nested mapping element.
</para>
@ -915,7 +927,7 @@
</sect2>
<sect2 id="mapping-declaration-discriminator" revision="2">
<sect2 id="mapping-declaration-discriminator" revision="3">
<title>discriminator</title>
<para>
@ -997,11 +1009,13 @@
that will be used to evaluate the type of a row:
</para>
<programlisting><![CDATA[<discriminator formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0 else 1 end" type="integer"/>]]></programlisting>
<programlisting><![CDATA[<discriminator
formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0 else 1 end"
type="integer"/>]]></programlisting>
</sect2>
<sect2 id="mapping-declaration-version">
<sect2 id="mapping-declaration-version" revision="1">
<title>version (optional)</title>
<para>
@ -1062,7 +1076,7 @@
</programlistingco>
<para>
Version numbers may be of type <literal>long</literal>, <literal>integer</literal>,
Version numbers may be of Hibernate type <literal>long</literal>, <literal>integer</literal>,
<literal>short</literal>, <literal>timestamp</literal> or <literal>calendar</literal>.
</para>
@ -1072,7 +1086,7 @@
no matter what other <literal>unsaved-value</literal> strategies are specified.
<emphasis>Declaring a nullable version or timestamp property is an easy way to avoid
any problems with transitive reattachment in Hibernate, especially useful for people
using assigned identiifers or composite keys!</emphasis>
using assigned identifiers or composite keys!</emphasis>
</para>
</sect2>
@ -1318,13 +1332,14 @@
</sect2>
<sect2 id="mapping-declaration-manytoone" revision="2">
<sect2 id="mapping-declaration-manytoone" revision="3">
<title>many-to-one</title>
<para>
An ordinary association to another persistent class is declared using a
<literal>many-to-one</literal> element. The relational model is a
many-to-one association. (Its really just an object reference.)
many-to-one association: a foreign key in one table is referencing
the primary key column(s) of the target table.
</para>
<programlistingco>
@ -1369,7 +1384,6 @@
<literal>column</literal> (optional): The name of the foreign key column.
This may also be specified by nested <literal>&lt;column&gt;</literal>
element(s).
</para>
</callout>
<callout arearefs="manytoone3">
@ -1437,11 +1451,10 @@
</programlistingco>
<para>
The <literal>cascade</literal> attribute permits the following values:
<literal>all</literal>, <literal>save-update</literal>, <literal>delete</literal>,
<literal>none</literal>. Setting a value other than <literal>none</literal>
will propagate certain operations to the associated (child) object.
See "Lifecycle Objects" below.
Setting a value of the <literal>cascade</literal> attribute to not
<literal>none</literal> will propagate certain operations to the
associated object (usually in a parent/child fashion). See
"Lifecycle Objects" discussed later.
</para>
<para>
@ -1621,7 +1634,7 @@
</sect2>
<sect2 id="mapping-declaration-component" revision="1">
<sect2 id="mapping-declaration-component" revision="2">
<title>component, dynamic-component</title>
<para>
@ -1692,15 +1705,15 @@
accessed (requires build-time bytecode instrumentation).
</para>
</callout>
<callout arearefs="component7">
<para>
<literal>optimistic-lock</literal> (optional - defaults to <literal>true</literal>):
Specifies that updates to this component do or do not require acquisition of the
optimistic lock. In other words, define if a version check should be made if this
property is dirty.
</para>
</callout>
</calloutlist>
<callout arearefs="component7">
<para>
<literal>optimistic-lock</literal> (optional - defaults to <literal>true</literal>):
Specifies that updates to this component do or do not require acquisition of the
optimistic lock. In other words, define if a version check should be made if this
property is dirty.
</para>
</callout>
</programlistingco>
<para>
@ -1716,17 +1729,18 @@
<para>
The <literal>&lt;dynamic-component&gt;</literal> element allows a <literal>Map</literal>
to be mapped as a component, where the property names refer to keys of the map.
to be mapped as a component, where the property names refer to keys of the map, see
<xref linken="components-dynamic"/>.
</para>
</sect2>
<sect2 id="mapping-declaration-subclass" revision="2">
<sect2 id="mapping-declaration-subclass" revision="3">
<title>subclass</title>
<para>
Finally, polymorphic persistence requires the declaration of each subclass of
the root persistent class. For the (recommended) table-per-class-hierarchy
the root persistent class. For the table-per-class-hierarchy
mapping strategy, the <literal>&lt;subclass&gt;</literal> declaration is used.
</para>
@ -1783,6 +1797,10 @@
fully qualified Java class name is used.
</para>
<para>
For information about inheritance mappings, see <xref linkend="inheritance"/>.
</para>
</sect2>
<sect2 id="mapping-declaration-joinedsubclass" revision="3">
@ -1884,9 +1902,13 @@
</hibernate-mapping>]]></programlisting>
<para>
For information about inheritance mappings, see <xref linkend="inheritance"/>.
</para>
</sect2>
<sect2 id="mapping-declaration-unionsubclass" revision="1">
<sect2 id="mapping-declaration-unionsubclass" revision="2">
<title>union-subclass</title>
<para>
@ -1896,7 +1918,7 @@
not absolutely necessary to explicitly map such inheritance hierarchies. You
can simply map each class with a separate <literal>&lt;class&gt;</literal>
declaration. However, if you wish use polymorphic associations (e.g. an association
directed at the superclass of your hierarchy), you need to
to the superclass of your hierarchy), you need to
use the <literal>&lt;union-subclass&gt;</literal> mapping.
</para>
@ -1954,6 +1976,10 @@
No discriminator column or key column is required for this mapping strategy.
</para>
<para>
For information about inheritance mappings, see <xref linkend="inheritance"/>.
</para>
</sect2>
<sect2 id="mapping-declaration-join" revision="3">
@ -2164,7 +2190,7 @@
<sect1 id="mapping-types">
<title>Hibernate Types</title>
<sect2 id="mapping-types-entitiesvalues">
<sect2 id="mapping-types-entitiesvalues" revision="1">
<title>Entities and values</title>
<para>
@ -2186,16 +2212,12 @@
<para>
An entity's persistent state consists of references to other entities and
instances of <emphasis>value</emphasis> types. Values are primitives,
collections, components and certain immutable objects. Unlike entities, values
(in particular collections and components) <emphasis>are</emphasis>
persisted and deleted by reachability. Since value objects (and primitives) are
persisted and deleted along with their containing entity they may not be
independently versioned. Values have no independent identity, so they cannot be
shared by two entities or collections.
</para>
<para>
All Hibernate types except collections support null semantics.
collections (not whats inside a collection), components and certain immutable
objects. Unlike entities, values (in particular collections and components)
<emphasis>are</emphasis> persisted and deleted by reachability. Since value
objects (and primitives) are persisted and deleted along with their containing
entity they may not be independently versioned. Values have no independent
identity, so they cannot be shared by two entities or collections.
</para>
<para>
@ -2203,14 +2225,43 @@
entities. We will continue to do that. Strictly speaking, however, not all
user-defined classes with persistent state are entities. A
<emphasis>component</emphasis> is a user defined class with value semantics.
A Java property of type <literal>java.lang.String</literal> also has value
semantics. Given this definition, we can say that all types (classes) provided
by the JDK have value type semantics in Java, while user-defined types may
be mapped with entity or value type semantics. This decision is up to the
application developer. A good hint for an entity class in a domain model are
shared references to a single instance of that class, while composition or
aggregation usually translates to a value type.
</para>
<para>
We'll revisit both concepts throughout the documentation.
</para>
<para>
The challenge is to map the Java type system (and the developers definition of
entities and value types) to the SQL/database type system. The bridge between
both systems is provided by Hibernate: for entities we use
<literal>&lt;class&gt;</literal>, <literal>&lt;subclass&lt;</literal> and so on.
For value types we use <literal>&lt;property&gt;</literal>,
<literal>&lt;component&gt;</literal>, etc, usually with a <literal>type</literal>
attribute. The value of this attribute is the name of a Hibernate
<emphasis>mapping type</emphasis>. Hibernate provides many mappings (for standard
JDK value types) out of the box. You can write your own mapping types and implement your
custom conversion strategies as well, as you'll see later.
</para>
<para>
All built-in Hibernate types except collections support null semantics.
</para>
</sect2>
<sect2 id="mapping-types-basictypes" revision="1">
<sect2 id="mapping-types-basictypes" revision="2">
<title>Basic value types</title>
<para>
The <emphasis>basic types</emphasis> may be roughly categorized into
The built-in <emphasis>basic mapping types</emphasis> may be roughly categorized into
<variablelist>
<varlistentry>
@ -2423,6 +2474,10 @@
</sect2>
<para>
TODO: document parameterizable usertypes
</para>
<sect2 id="mapping-types-anymapping" revision="2">
<title>Any type mappings</title>
@ -2544,7 +2599,7 @@
<literal>hibernate-mapping</literal>. This allows you to extend a class hierachy just 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 Hibernate 3, the ordering of mapping files does not matter when using the
documents important. Since Hibernate3, the ordering of mapping files does not matter when using the
extends keyword. The ordering inside a single mapping file still needs to be defined as superclasses
before subclasses.
</para>
@ -2585,7 +2640,7 @@ public class Cat {
private char sex;
private float weight;
/**
/*
* @hibernate.id
* generator-class="native"
* column="CAT_ID"
@ -2693,6 +2748,34 @@ public class Cat {
package, as a separate download. Both EJB3 (JSR-220) and Hibernate3 metadata is supported.
</para>
<para>
This is an example of a POJO class annotated as an EJB entity bean:
</para>
<programlisting><![CDATA[@Entity(access = AccessType.FIELD)
public class Customer implements Serializable {
@Id;
Long id;
String firstName;
String lastName;
Date birthday;
@Transient
Integer age;
@Dependent
private Address homeAddress;
@OneToMany(cascade=CascadeType.ALL,
targetEntity="Order")
@JoinColumn(name="CUSTOMER_ID")
Set orders;
// Getter/setter and business methods
}]]></programlisting>
<para>
Note that support for JDK 5.0 Annotations (and JSR-220) is still work in progress and
not completed.

View File

@ -797,16 +797,13 @@ hibernate.dialect = \
</tgroup>
</table>
<sect2 id="configuration-optional-dialects">
<sect2 id="configuration-optional-dialects" revision="1">
<title>SQL Dialects</title>
<para>
You should always set the <literal>hibernate.dialect</literal> property to the correct
<literal>org.hibernate.dialect.Dialect</literal> subclass for your database. This is not
strictly essential unless you wish to use <literal>native</literal> or
<literal>sequence</literal> primary key generation or pessimistic locking (with, eg.
<literal>Session.lock()</literal> or <literal>Query.setLockMode()</literal>).
However, if you specify a dialect, Hibernate will use sensible defaults for some of the
<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.
</para>
@ -931,23 +928,24 @@ hibernate.dialect = \
</sect2>
<sect2 id="configuration-optional-cacheprovider" revision="1">
<sect2 id="configuration-optional-cacheprovider" revision="2">
<title>Second-level and query cache</title>
<para>
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 "Performance" chapter for more details.
with Hibernate. See the <xref linkend="performance-cache"/> for
more details.
</para>
</sect2>
<sect2 id="configuration-optional-transactionstrategy" revision="1">
<sect2 id="configuration-optional-transactionstrategy" revision="3">
<title>Transaction strategy configuration</title>
<para>
If you wish to use the Hibernate <literal>Transaction</literal> API instead
of directly calling a particular transaction API, you must
of directly calling a particular system 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
@ -980,9 +978,10 @@ hibernate.dialect = \
</para>
<para>
If you wish to use a second-level cache for mutable data in a JTA environment, you must specify
a strategy for obtaining the JTA <literal>TransactionManager</literal>, since J2EE does not
standardize a single mechanism:
Some features in Hibernate (i.e. the second level cache) require access to the
JTA <literal>TransactionManager</literal> in a management environment. You have to
specify how Hibernate should obtain a reference to the <literal>TransactionManager</literal>,
since J2EE does not standardize a single mechanism:
</para>
<table frame="topbot" id="jtamanagerlookup" revision="1">
@ -1039,7 +1038,7 @@ hibernate.dialect = \
</sect2>
<sect2 id="configuration-optional-jndi" revision="1">
<sect2 id="configuration-optional-jndi" revision="2">
<title>JNDI-bound <literal>SessionFactory</literal></title>
<para>
@ -1066,7 +1065,8 @@ hibernate.dialect = \
<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.
this call in some startup code (or utility class) in your application, unless you use
JMX deployment with the <literal>HibernateService</literal>.
</para>
<para>
@ -1101,14 +1101,15 @@ hibernate.dialect = \
</sect2>
<sect2 id="configuration-optional-statistics" revision="1">
<sect2 id="configuration-optional-statistics" revision="2">
<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
<literal>SessionFactory.getStatistics()</literal>. Hibernate can even be configured
to expose these statistics via JMX (see the website for details).
to expose these statistics via JMX. Read the Javadoc of the interfaces in
<literal>org.hibernate.stats</literal> for more information.
</para>
</sect2>
@ -1177,8 +1178,8 @@ hibernate.dialect = \
</sect1>
<sect1 id="configuration-xmlconfig" revision="1">
<title>XML Configuration File</title>
<sect1 id="configuration-xmlconfig" revision="2">
<title>XML configuration file</title>
<para>
An alternative approach to configuration is to specify a full configuration in
@ -1216,6 +1217,11 @@ hibernate.dialect = \
<mapping resource="org/hibernate/auction/Item.hbm.xml"/>
<mapping resource="org/hibernate/auction/Bid.hbm.xml"/>
<!-- cache settings -->
<class-cache class="org.hibernate.auction.Item" usage="read-write"/>
<class-cache class="org.hibernate.auction.Bid" usage="read-only"/>
<collection-cache class="org.hibernate.auction.Item.bids" usage="read-write"/>
</session-factory>
</hibernate-configuration>]]></programlisting>
@ -1223,11 +1229,14 @@ hibernate.dialect = \
<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.
is also more convenient once you have to tune the Hibernate cache. Note that is
your choice to use either <literal>hibernate.properties</literal> or
<literal>hibernate.cfg.xml</literal>, both are equivalent, except for the above
mentioned benefits of using the XML syntax.
</para>
<para>
Configuring 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>

View File

@ -12,7 +12,7 @@
Hibernate works best if these classes follow some simple rules, also known
as the Plain Old Java Object (POJO) programming model. However, Hibernate3
allows you to express a domain model in other ways: using trees of
<literal>Map</literal> instances, for example.
<literal>Map</literal> instances, for example.
</para>
<sect1 id="persistent-classes-pojo">
@ -134,16 +134,16 @@ public class Cat {
persistent classes must have a default constructor (which may be non-public) so
Hibernate can instantiate them using <literal>Constructor.newInstance()</literal>.
We recommend having a constructor with at least <emphasis>package</emphasis>
visibility for runtime proxy generation in Hibernate.
visibility for runtime proxy generation in Hibernate.
</para>
</sect2>
<sect2 id="persistent-classes-pojo-identifier">
<sect2 id="persistent-classes-pojo-identifier" revision="1">
<title>Provide an identifier property (optional)</title>
<para>
<literal>Cat</literal> has a property called <literal>id</literal>. This property
holds the primary key column of a database table. The property might have been called
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
@ -165,7 +165,7 @@ public class Cat {
<listitem>
<para>
Transitive reattachment for detached objects (cascade update) -
see "Lifecycle Objects"
see "Lifecycle Objects"
</para>
</listitem>
<listitem>
@ -190,8 +190,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 associationfetching -
which will limit your options for performance tuning.
with Hibernate, but you won't be able to use proxies for lazy association fetching -
which will limit your options for performance tuning.
</para>
</sect2>
@ -219,20 +219,20 @@ public class DomesticCat extends Cat {
}]]></programlisting>
</sect1>
<sect1 id="persistent-classes-equalshashcode">
<sect1 id="persistent-classes-equalshashcode" revision="1">
<title>Implementing <literal>equals()</literal> and <literal>hashCode()</literal></title>
<para>
You have to override the <literal>equals()</literal> and <literal>hashCode()</literal>
methods if you
</para>
</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)
<emphasis>and</emphasis>
</para>
<emphasis>and</emphasis>
</para>
</listitem>
<listitem>
<para>
@ -243,10 +243,10 @@ 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
<literal>Set</literal>s.
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
<literal>Set</literal>s.
</para>
<para>
@ -255,15 +255,20 @@ public class DomesticCat extends Cat {
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! We recommend
implementing <literal>equals()</literal> and <literal>hashCode()</literal> using
<emphasis>Business key equality</emphasis>.
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.
</para>
<para>
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 <emphasis>natural</emphasis> candidate key):
We recommend implementing <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
<emphasis>natural</emphasis> candidate key):
</para>
<programlisting><![CDATA[public class Cat {
@ -290,9 +295,15 @@ public class DomesticCat extends Cat {
}]]></programlisting>
<para>
Note that a business key does not have to be as solid as a database
primary key candidate. Immutable or unique properties are usually good
candidates for a business key.
</para>
</sect1>
<sect1 id="persistent-classes-dynamic" revision="1">
<sect1 id="persistent-classes-dynamic" revision="2">
<title>Dynamic models</title>
<para>
@ -306,27 +317,27 @@ public class DomesticCat extends Cat {
<dynamic-class entity-name="TestMap">
<id name="id"
type="long"
column="ID">
type="long"
column="ID">
<generator class="sequence"/>
</id>
<property name="name"
column="NAME"
type="string"/>
column="NAME"
type="string"/>
<property name="address"
column="ADDRESS"
type="string"/>
column="ADDRESS"
type="string"/>
<many-to-one name="parent"
column="PARENT_ID"
class="TestMap"/>
column="PARENT_ID"
class="TestMap"/>
<bag name="children"
inverse="true"
lazy="false"
cascade="all">
inverse="true"
lazy="false"
cascade="all">
<key column="PARENT_ID"/>
<one-to-many class="TestMap"/>
</bag>
@ -337,7 +348,7 @@ public class DomesticCat extends Cat {
<para>
At runtime, you just instantiate <literal>HashMap</literal>s and use
the Hibernate entity name to refer to a particular type.
the Hibernate entity name to refer to a particular type:
</para>
<programlisting><![CDATA[Session s = openSession();