doc'd new lazy stuff
added node examples git-svn-id: https://svn.jboss.org/repos/hibernate/trunk/Hibernate3/doc@6648 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
92359983cc
commit
617a17a15b
|
@ -237,6 +237,8 @@
|
|||
<area id="class19" coords="20 55"/>
|
||||
<area id="class20" coords="21 55"/>
|
||||
<area id="class21" coords="22 55"/>
|
||||
<area id="class22" coords="23 55"/>
|
||||
<area id="class23" coords="24 55"/>
|
||||
</areaspec>
|
||||
<programlisting><![CDATA[<class
|
||||
name="ClassName"
|
||||
|
@ -261,6 +263,7 @@
|
|||
subselect="SQL expression"
|
||||
abstract="true|false"
|
||||
entity-name="EntityName"
|
||||
node="element-name"
|
||||
/>]]></programlisting>
|
||||
<calloutlist>
|
||||
<callout arearefs="class1">
|
||||
|
@ -403,6 +406,12 @@
|
|||
<literal><union-subclass></literal> hierarchies.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="class22">
|
||||
<para>
|
||||
<literal>entity-name</literal> (optional, defaults to the class name): Explicitly
|
||||
specify an entity name.
|
||||
</para>
|
||||
</callout>
|
||||
</calloutlist>
|
||||
</programlistingco>
|
||||
|
||||
|
@ -537,11 +546,11 @@
|
|||
|
||||
<programlistingco>
|
||||
<areaspec>
|
||||
<area id="id1" coords="2 65"/>
|
||||
<area id="id2" coords="3 65" />
|
||||
<area id="id3" coords="4 65"/>
|
||||
<area id="id4" coords="5 65" />
|
||||
<area id="id5" coords="6 65" />
|
||||
<area id="id1" coords="2 70"/>
|
||||
<area id="id2" coords="3 70" />
|
||||
<area id="id3" coords="4 70"/>
|
||||
<area id="id4" coords="5 70" />
|
||||
<area id="id5" coords="6 70" />
|
||||
</areaspec>
|
||||
<programlisting><![CDATA[<id
|
||||
name="propertyName"
|
||||
|
@ -549,6 +558,7 @@
|
|||
column="column_name"
|
||||
unsaved-value="null|any|none|undefined|id_value"
|
||||
access="field|property|ClassName">
|
||||
node="element-name|@attribute-name|element/@attribute|."
|
||||
|
||||
<generator class="generatorClass"/>
|
||||
</id>]]></programlisting>
|
||||
|
@ -861,6 +871,7 @@
|
|||
class="ClassName"
|
||||
unsaved-value="undefined|any|none"
|
||||
access="field|property|ClassName">
|
||||
node="element-name|."
|
||||
|
||||
<key-property name="propertyName" type="typename" column="column_name"/>
|
||||
<key-many-to-one name="propertyName class="ClassName" column="column_name"/>
|
||||
|
@ -1020,11 +1031,11 @@
|
|||
|
||||
<programlistingco>
|
||||
<areaspec>
|
||||
<area id="version1" coords="2 60"/>
|
||||
<area id="version2" coords="3 60"/>
|
||||
<area id="version3" coords="4 60"/>
|
||||
<area id="version4" coords="5 60"/>
|
||||
<area id="version5" coords="6 60"/>
|
||||
<area id="version1" coords="2 70"/>
|
||||
<area id="version2" coords="3 70"/>
|
||||
<area id="version3" coords="4 70"/>
|
||||
<area id="version4" coords="5 70"/>
|
||||
<area id="version5" coords="6 70"/>
|
||||
</areaspec>
|
||||
<programlisting><![CDATA[<version
|
||||
column="version_column"
|
||||
|
@ -1032,6 +1043,7 @@
|
|||
type="typename"
|
||||
access="field|property|ClassName"
|
||||
unsaved-value="null|negative|undefined"
|
||||
node="element-name|@attribute-name|element/@attribute|."
|
||||
/>]]></programlisting>
|
||||
<calloutlist>
|
||||
<callout arearefs="version1">
|
||||
|
@ -1096,16 +1108,17 @@
|
|||
|
||||
<programlistingco>
|
||||
<areaspec>
|
||||
<area id="timestamp1" coords="2 45"/>
|
||||
<area id="timestamp2" coords="3 45" />
|
||||
<area id="timestamp3" coords="4 45" />
|
||||
<area id="timestamp4" coords="5 45" />
|
||||
<area id="timestamp1" coords="2 70"/>
|
||||
<area id="timestamp2" coords="3 70" />
|
||||
<area id="timestamp3" coords="4 70" />
|
||||
<area id="timestamp4" coords="5 70" />
|
||||
</areaspec>
|
||||
<programlisting><![CDATA[<timestamp
|
||||
column="timestamp_column"
|
||||
name="propertyName"
|
||||
access="field|property|ClassName"
|
||||
unsaved-value="null|undefined"
|
||||
node="element-name|@attribute-name|element/@attribute|."
|
||||
/>]]></programlisting>
|
||||
<calloutlist>
|
||||
<callout arearefs="timestamp1">
|
||||
|
@ -1156,19 +1169,19 @@
|
|||
|
||||
<programlistingco>
|
||||
<areaspec>
|
||||
<area id="property1" coords="2 45"/>
|
||||
<area id="property2" coords="3 45"/>
|
||||
<area id="property3" coords="4 45"/>
|
||||
<area id="property1" coords="2 70"/>
|
||||
<area id="property2" coords="3 70"/>
|
||||
<area id="property3" coords="4 70"/>
|
||||
<areaset id="property4-5" coords="">
|
||||
<area id="property4" coords='5 45'/>
|
||||
<area id="property5" coords='6 45'/>
|
||||
<area id="property4" coords='5 70'/>
|
||||
<area id="property5" coords='6 70'/>
|
||||
</areaset>
|
||||
<area id="property6" coords="7 45"/>
|
||||
<area id="property7" coords="8 45"/>
|
||||
<area id="property8" coords="9 45"/>
|
||||
<area id="property9" coords="10 45"/>
|
||||
<area id="property10" coords="11 45"/>
|
||||
<area id="property11" coords="12 45"/>
|
||||
<area id="property6" coords="7 70"/>
|
||||
<area id="property7" coords="8 70"/>
|
||||
<area id="property8" coords="9 70"/>
|
||||
<area id="property9" coords="10 70"/>
|
||||
<area id="property10" coords="11 70"/>
|
||||
<area id="property11" coords="12 70"/>
|
||||
</areaspec>
|
||||
<programlisting><![CDATA[<property
|
||||
name="propertyName"
|
||||
|
@ -1182,6 +1195,7 @@
|
|||
unique="true|false"
|
||||
not-null="true|false"
|
||||
optimistic-lock="true|false"
|
||||
node="element-name|@attribute-name|element/@attribute|."
|
||||
/>]]></programlisting>
|
||||
<calloutlist>
|
||||
<callout arearefs="property1">
|
||||
|
@ -1338,22 +1352,23 @@
|
|||
|
||||
<programlistingco>
|
||||
<areaspec>
|
||||
<area id="manytoone1" coords="2 60"/>
|
||||
<area id="manytoone2" coords="3 60"/>
|
||||
<area id="manytoone3" coords="4 60"/>
|
||||
<area id="manytoone4" coords="5 60"/>
|
||||
<area id="manytoone5" coords="6 60"/>
|
||||
<area id="manytoone1" coords="2 70"/>
|
||||
<area id="manytoone2" coords="3 70"/>
|
||||
<area id="manytoone3" coords="4 70"/>
|
||||
<area id="manytoone4" coords="5 70"/>
|
||||
<area id="manytoone5" coords="6 70"/>
|
||||
<areaset id="manytoone6-7" coords="">
|
||||
<area id="manytoone6" coords='7 60'/>
|
||||
<area id="manytoone7" coords='8 60'/>
|
||||
<area id="manytoone6" coords='7 70'/>
|
||||
<area id="manytoone7" coords='8 70'/>
|
||||
</areaset>
|
||||
<area id="manytoone8" coords="9 60"/>
|
||||
<area id="manytoone9" coords="10 60"/>
|
||||
<area id="manytoone10" coords="11 60"/>
|
||||
<area id="manytoone11" coords="12 60"/>
|
||||
<area id="manytoone12" coords="13 60"/>
|
||||
<area id="manytoone13" coords="14 60"/>
|
||||
<area id="manytoone14" coords="15 60"/>
|
||||
<area id="manytoone8" coords="9 70"/>
|
||||
<area id="manytoone9" coords="10 70"/>
|
||||
<area id="manytoone10" coords="11 70"/>
|
||||
<area id="manytoone11" coords="12 70"/>
|
||||
<area id="manytoone12" coords="13 70"/>
|
||||
<area id="manytoone13" coords="14 70"/>
|
||||
<area id="manytoone14" coords="15 70"/>
|
||||
<area id="manytoone15" coords="16 70"/>
|
||||
</areaspec>
|
||||
<programlisting><![CDATA[<many-to-one
|
||||
name="propertyName"
|
||||
|
@ -1368,9 +1383,11 @@
|
|||
unique="true|false"
|
||||
not-null="true|false"
|
||||
optimistic-lock="true|false"
|
||||
lazy="true|false"
|
||||
lazy="true|proxy|false"
|
||||
not-found="ignore|exception"
|
||||
entity-name="EntityName"
|
||||
node="element-name|@attribute-name|element/@attribute|."
|
||||
embed-xml="true|false"
|
||||
/>]]></programlisting>
|
||||
<calloutlist>
|
||||
<callout arearefs="manytoone1">
|
||||
|
@ -1449,11 +1466,12 @@
|
|||
</callout>
|
||||
<callout arearefs="manytoone13">
|
||||
<para>
|
||||
<literal>lazy</literal> (optional - defaults to <literal>false</literal>): Specifies
|
||||
that this property should be fetched lazily when the instance variable is first
|
||||
accessed (requires build-time bytecode instrumentation). Note that this does not
|
||||
influence Hibernate's proxy behavior - like the <literal>lazy</literal> attribute
|
||||
on class or collection mappings, but uses interception for deferred loading.
|
||||
<literal>lazy</literal> (optional - defaults to <literal>proxy</literal>):
|
||||
By default, single point associations are proxied. <literal>lazy="true"</literal>
|
||||
specifies that the property should be fetched lazily when the instance variable
|
||||
is first accessed (requires build-time bytecode instrumentation).
|
||||
<literal>lazy="false"</literal> specifies that the association will always
|
||||
be eagerly fetched.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="manytoone14">
|
||||
|
@ -1463,6 +1481,11 @@
|
|||
<literal>ignore</literal> will treat a missing row as a null association.
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="manytoone15">
|
||||
<para>
|
||||
<literal>entity-name</literal> (optional): The entity name of the associated class.
|
||||
</para>
|
||||
</callout>
|
||||
</calloutlist>
|
||||
</programlistingco>
|
||||
|
||||
|
@ -1522,14 +1545,16 @@
|
|||
|
||||
<programlistingco>
|
||||
<areaspec>
|
||||
<area id="onetoone1" coords="2 60"/>
|
||||
<area id="onetoone2" coords="3 60"/>
|
||||
<area id="onetoone3" coords="4 60"/>
|
||||
<area id="onetoone4" coords="5 60"/>
|
||||
<area id="onetoone5" coords="6 60"/>
|
||||
<area id="onetoone6" coords="7 60"/>
|
||||
<area id="onetoone7" coords="8 60"/>
|
||||
<area id="onetoone8" coords="9 60"/>
|
||||
<area id="onetoone1" coords="2 70"/>
|
||||
<area id="onetoone2" coords="3 70"/>
|
||||
<area id="onetoone3" coords="4 70"/>
|
||||
<area id="onetoone4" coords="5 70"/>
|
||||
<area id="onetoone5" coords="6 70"/>
|
||||
<area id="onetoone6" coords="7 70"/>
|
||||
<area id="onetoone7" coords="8 70"/>
|
||||
<area id="onetoone8" coords="9 70"/>
|
||||
<area id="onetoone9" coords="10 70"/>
|
||||
<area id="onetoone10" coords="11 70"/>
|
||||
</areaspec>
|
||||
<programlisting><![CDATA[<one-to-one
|
||||
name="propertyName"
|
||||
|
@ -1540,7 +1565,10 @@
|
|||
property-ref="propertyNameFromAssociatedClass"
|
||||
access="field|property|ClassName"
|
||||
formula="any SQL expression"
|
||||
lazy="true|proxy|false"
|
||||
entity-name="EntityName"
|
||||
node="element-name|@attribute-name|element/@attribute|."
|
||||
embed-xml="true|false"
|
||||
/>]]></programlisting>
|
||||
<calloutlist>
|
||||
<callout arearefs="onetoone1">
|
||||
|
@ -1596,6 +1624,22 @@
|
|||
<literal>org.hibernate.test.onetooneformula</literal> for an example.)
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="onetoone9">
|
||||
<para>
|
||||
<literal>lazy</literal> (optional - defaults to <literal>proxy</literal>):
|
||||
By default, single point associations are proxied. <literal>lazy="true"</literal>
|
||||
specifies that the property should be fetched lazily when the instance variable
|
||||
is first accessed (requires build-time bytecode instrumentation).
|
||||
<literal>lazy="false"</literal> specifies that the association will always
|
||||
be eagerly fetched. <emphasis>Note that if <literal>constrained="false"</literal>,
|
||||
proxying is impossible and Hibernate will eager fetch the association!</emphasis>
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="onetoone10">
|
||||
<para>
|
||||
<literal>entity-name</literal> (optional): The entity name of the associated class.
|
||||
</para>
|
||||
</callout>
|
||||
</calloutlist>
|
||||
</programlistingco>
|
||||
|
||||
|
@ -1696,6 +1740,7 @@
|
|||
lazy="true|false"
|
||||
optimistic-lock="true|false"
|
||||
unique="true|false"
|
||||
node="element-name|."
|
||||
>
|
||||
|
||||
<property ...../>
|
||||
|
@ -1901,7 +1946,8 @@
|
|||
lazy="true|false"
|
||||
dynamic-update="true|false"
|
||||
dynamic-insert="true|false"
|
||||
entity-name="EntityName">
|
||||
entity-name="EntityName"
|
||||
node="element-name">
|
||||
|
||||
<property .... />
|
||||
.....
|
||||
|
@ -1993,7 +2039,8 @@
|
|||
extends="SuperclassName"
|
||||
persister="ClassName"
|
||||
subselect="SQL expression"
|
||||
entity-name="EntityName">
|
||||
entity-name="EntityName"
|
||||
node="element-name">
|
||||
|
||||
<key .... >
|
||||
|
||||
|
@ -2105,7 +2152,8 @@
|
|||
abstract="true|false"
|
||||
persister="ClassName"
|
||||
subselect="SQL expression"
|
||||
entity-name="EntityName">
|
||||
entity-name="EntityName"
|
||||
node="element-name">
|
||||
|
||||
<property .... />
|
||||
.....
|
||||
|
|
|
@ -129,6 +129,8 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
|
|||
batch-size="N"
|
||||
access="field|property|ClassName"
|
||||
optimistic-lock="true|false"
|
||||
node="element-name|."
|
||||
embed-xml="true|false"
|
||||
>
|
||||
|
||||
<key .... />
|
||||
|
@ -156,7 +158,8 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
|
|||
<callout arearefs="mappingcollection4">
|
||||
<para>
|
||||
<literal>lazy</literal> (optional - defaults to <literal>true</literal>)
|
||||
enable lazy initialization (not available for arrays)
|
||||
may be used to disable lazy fetching and specify that the association is
|
||||
always eagerly fetched (not available for arrays)
|
||||
</para>
|
||||
</callout>
|
||||
<callout arearefs="mappingcollection5">
|
||||
|
@ -328,6 +331,7 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
|
|||
column="column_name"
|
||||
formula="any SQL expression"
|
||||
type="type_name"
|
||||
node="@attribute-name"
|
||||
length="N"/>]]></programlisting>
|
||||
<calloutlist>
|
||||
<callout arearefs="mapkey1">
|
||||
|
@ -464,6 +468,7 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
|
|||
<area id="manytomany4" coords="5 60"/>
|
||||
<area id="manytomany5" coords="6 60"/>
|
||||
<area id="manytomany6" coords="7 60"/>
|
||||
<area id="manytomany7" coords="8 60"/>
|
||||
</areaspec>
|
||||
<programlisting><![CDATA[<many-to-many
|
||||
column="column_name"
|
||||
|
@ -473,6 +478,8 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
|
|||
unique="true|false"
|
||||
not-found="ignore|exception"
|
||||
entity-name="EntityName"
|
||||
node="element-name|element/@attribute"
|
||||
embed-xml="true|false"
|
||||
/>]]></programlisting>
|
||||
<calloutlist>
|
||||
<callout arearefs="manytomany1">
|
||||
|
@ -516,6 +523,12 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
|
|||
<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,
|
||||
as an alternative to <literal>class</literal>.
|
||||
</para>
|
||||
</callout>
|
||||
</calloutlist>
|
||||
</programlistingco>
|
||||
|
||||
|
@ -617,11 +630,15 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
|
|||
<areaspec>
|
||||
<area id="onetomany1" coords="2 60"/>
|
||||
<area id="onetomany2" coords="3 60"/>
|
||||
<area id="onetomany3" coords="4 60"/>
|
||||
</areaspec>
|
||||
<programlisting><![CDATA[<one-to-many
|
||||
class="ClassName"
|
||||
not-found="ignore|exception"
|
||||
entity-name="EntityName"/>]]></programlisting>
|
||||
entity-name="EntityName"
|
||||
node="element-name|element/@attribute"
|
||||
embed-xml="true|false"
|
||||
/>]]></programlisting>
|
||||
<calloutlist>
|
||||
<callout arearefs="onetomany1">
|
||||
<para>
|
||||
|
@ -635,6 +652,12 @@ kittens = cat.getKittens(); // Okay, kittens collection is a Set
|
|||
<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,
|
||||
as an alternative to <literal>class</literal>.
|
||||
</para>
|
||||
</callout>
|
||||
</calloutlist>
|
||||
</programlistingco>
|
||||
|
||||
|
|
|
@ -5,11 +5,10 @@
|
|||
<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 particular HQL or
|
||||
<literal>Criteria</literal> query.
|
||||
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
|
||||
particular HQL or <literal>Criteria</literal> query.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -51,25 +50,77 @@
|
|||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
By default, Hibernate3 uses lazy select fetching, which is the best choice for most entities
|
||||
and collections in most applications. If you set
|
||||
<literal>hibernate.default_batch_fetch_size</literal>, Hibernate will use the batch fetch
|
||||
optimization to lazy fetching (this optimization may also be enabled at a more granular level).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
However, there is one problem to be aware of. Access to a lazy association
|
||||
outside of the context of an open Hibernate session will result in an exception.
|
||||
For example:
|
||||
Hibernate also distinguishes between:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<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.)
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<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>Lazy attribute fetching</emphasis> - an attribute or single
|
||||
valued association is fetched when the instance variable is accessed
|
||||
(required buildtime bytecode instrumentation). This approach is
|
||||
rarely necessary.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<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
|
||||
<literal>lazy</literal> to define a contract for what data is always available
|
||||
in any detached instance of a particular class.
|
||||
</para>
|
||||
|
||||
<sect2 id="performance-fetching-lazy">
|
||||
<title>Working with lazy associations</title>
|
||||
|
||||
<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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<emphasis>Note:</emphasis> 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).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
However, lazy fetching poses one problem that you must be aware of. Access to a
|
||||
lazy association outside of the context of an open Hibernate session will result
|
||||
in an exception. For example:
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[s = sessions.openSession();
|
||||
Transaction tx = s.beginTransaction();
|
||||
|
||||
User u = (User) s.createQuery("from User u where u.name=:userName")
|
||||
.setString("userName", userName).uniqueResult();
|
||||
.setString("userName", userName).uniqueResult();
|
||||
Map permissions = u.getPermissions();
|
||||
|
||||
tx.commit();
|
||||
|
@ -77,40 +128,41 @@ s.close();
|
|||
|
||||
Integer accessLevel = (Integer) permissions.get("accounts"); // Error!]]></programlisting>
|
||||
|
||||
<para>
|
||||
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 from the collection to just before the commit. (There are
|
||||
other more advanced ways to solve this problem, some are discussed later.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is also possible to use a non-lazy collection or join fetching, which is
|
||||
non-lazy by nature. However, it is intended that lazy initialization be used
|
||||
for almost all collections, especially for collections of entity references.
|
||||
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!
|
||||
</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
|
||||
how to customize the fetching strategy. In Hibernate3, the mechanisms for
|
||||
choosing a fetch strategy are identical for single-valued associations and
|
||||
collections.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
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
|
||||
from the collection to just before the transaction is committed.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Alternatively, we could 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!
|
||||
</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
|
||||
how to customize the fetching strategy. In Hibernate3, the mechanisms for
|
||||
choosing a fetch strategy are identical for single-valued associations and
|
||||
collections.
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
<sect2 id="performance-fetching-custom" revision="3">
|
||||
<title>Tuning fetch strategies</title>
|
||||
|
||||
<para>
|
||||
Select fetching (the default) is extremely vulnerable to N+1 selects problems,
|
||||
so we might want to enable join fetching in the mapping document:
|
||||
</para>
|
||||
|
||||
|
||||
<para>
|
||||
Select fetching (the default) is extremely vulnerable to N+1 selects problems,
|
||||
so we might want to enable join fetching in the mapping document:
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[<set name="permissions"
|
||||
fetch="join">
|
||||
<key column="userId"/>
|
||||
|
@ -142,10 +194,10 @@ Integer accessLevel = (Integer) permissions.get("accounts"); // Error!]]></prog
|
|||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
<emphasis>Specifying <literal>join</literal> as the fetch strategy in the mapping
|
||||
document does not affect HQL queries.</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
<emphasis>Specifying <literal>join</literal> as the fetch strategy in the mapping
|
||||
document does not affect HQL queries.</emphasis>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Usually, we don't use the mapping document to customize fetching. Instead, we
|
||||
|
@ -157,16 +209,16 @@ 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 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:
|
||||
</para>
|
||||
|
||||
<programlisting><![CDATA[User user = (User) session.createCriteria(User.class)
|
||||
.setFetchMode("permissions", FetchMode.JOIN)
|
||||
.add( Restrictions.idEq(userId) )
|
||||
.uniqueResult();]]></programlisting>
|
||||
|
||||
.setFetchMode("permissions", FetchMode.JOIN)
|
||||
.add( Restrictions.idEq(userId) )
|
||||
.uniqueResult();]]></programlisting>
|
||||
|
||||
<para>
|
||||
(This is Hibernate's equivalent of what some ORM solutions call a "fetch plan".)
|
||||
</para>
|
||||
|
|
Loading…
Reference in New Issue