Sunday, June 24, 2007

Hibernate fetching strategies

A fetching strategy 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 Criteria query.

Hibernate3 defines the following fetching strategies:

  • Join fetching - Hibernate retrieves the associated instance or collection in the same SELECT, using an OUTER JOIN.

    <set name="permissions" fetch="join">
    <key column="userId"/>
    <one-to-many class="Permission"/>
    </set


    <many-to-one name="mother" class="Cat" fetch="join"/>


    Can be specified at query level:


    User user = (User) session.createCriteria(User.class)
    .setFetchMode("permissions", FetchMode.JOIN)
    .add( Restrictions.idEq(userId) )
    .uniqueResult();
  • Select fetching - a second SELECT is used to retrieve the associated entity or collection. Unless you explicitly disable lazy fetching by specifying lazy="false", this second select will only be executed when you actually access the association. Use fetch="select" or FetchMode?.Select to accomplish this.
  • Subselect fetching - a second SELECT 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 lazy="false", this second select will only be executed when you actually access the association. Use fetch="subselect" or FetchMode?.SubSelect? to accomplish this.

* Batch fetching - an optimization strategy for select fetching - Hibernate retrieves a batch of entity instances or collections in a single SELECT, by specifying a list of primary keys or foreign keys. You may also enable batch fetching of collections. For example, if each Person has a lazy collection of Cats, and 10 persons are currently loaded in the Sesssion, iterating through all persons will generate 10 SELECTs, one for every call to getCats(). If you enable batch fetching for the cats collection in the mapping of Person, Hibernate can pre-fetch collections. With a batch-size of 8, Hibernate will load 3, 3, 3, 1 collections in four SELECTs. Again, the value of the attribute depends on the expected number of uninitialized collections in a particular Session. Batch fetching of collections is particularly useful if you have a nested tree of items, ie. the typical bill-of-materials pattern. (Although a nested set or a materialized path might be a better option for read-mostly trees.)

<class name="Person">
<set name="cats" batch-size="3">
...
</set>
</class>


Hibernate also distinguishes between:

  • Immediate fetching - an association, collection or attribute is fetched immediately, when the owner is loaded.
  • Lazy collection fetching - a collection is fetched when the application invokes an operation upon that collection. (This is the default for collections.)
  • "Extra-lazy" collection fetching - 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)
  • Proxy fetching - a single-valued association is fetched when a method other than the identifier getter is invoked upon the associated object.
  • "No-proxy" fetching - 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 the application. This approach requires buildtime bytecode instrumentation and is rarely necessary.
  • Lazy attribute fetching - an attribute or single valued association is fetched when the instance variable is accessed. This approach requires buildtime bytecode instrumentation and is rarely necessary.

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.


To enable lazy property loading, set the lazy attribute on your particular property mappings:

<class name="Document">
<id name="id">
<generator class="native"/>
</id>
<property name="name" not-null="true" length="50"/>
<property name="summary" not-null="true" length="200" lazy="true"/>
<property name="text" not-null="true" length="2000" lazy="true"/>
</class>

No comments:

Post a Comment