<?xml version='1.0' encoding="UTF-8"?>
<!--
  ~ Hibernate, Relational Persistence for Idiomatic Java
  ~
  ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
  ~ indicated by the @author tags or express copyright attribution
  ~ statements applied by the authors.  All third-party contributions are
  ~ distributed under license by Red Hat Middleware LLC.
  ~
  ~ This copyrighted material is made available to anyone wishing to use, modify,
  ~ copy, or redistribute it subject to the terms and conditions of the GNU
  ~ Lesser General Public License, as published by the Free Software Foundation.
  ~
  ~ This program is distributed in the hope that it will be useful,
  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  ~ or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
  ~ for more details.
  ~
  ~ You should have received a copy of the GNU Lesser General Public License
  ~ along with this distribution; if not, write to:
  ~ Free Software Foundation, Inc.
  ~ 51 Franklin Street, Fifth Floor
  ~ Boston, MA  02110-1301  USA
  -->

<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "../HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent">
%BOOK_ENTITIES;

]>

<chapter id="best-practices" revision="3">
    <title>Best Practices</title>

    <variablelist spacing="compact">
        <varlistentry>
            <term>Write fine-grained classes and map them using <literal>&lt;component&gt;</literal>:</term>
            <listitem>
                <para>
                    Use an <literal>Address</literal> class to encapsulate <literal>street</literal>,
                    <literal>suburb</literal>, <literal>state</literal>, <literal>postcode</literal>.
                    This encourages code reuse and simplifies refactoring.
                </para>
            </listitem>
        </varlistentry>
        <varlistentry>
            <term>Declare identifier properties on persistent classes:</term>
            <listitem>
                <para>
                    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>
            <listitem>
                <para>
                    Identify natural keys for all entities, and map them using 
                    <literal>&lt;natural-id&gt;</literal>. Implement <literal>equals()</literal> and 
                    <literal>hashCode()</literal> to compare the properties that make up the natural key.
                </para>
            </listitem>
        </varlistentry>
        <varlistentry>
            <term>Place each class mapping in its own file:</term>
            <listitem>
                <para>
                     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>
            <listitem>
                <para>
                    Deploy the mappings along with the classes they map.
                </para>
            </listitem>
        </varlistentry>
        <varlistentry>
            <term>Consider externalizing query strings:</term>
            <listitem>
                <para>
                    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>
        </varlistentry>
        <varlistentry>
            <term>Use bind variables.</term>
            <listitem>
                <para>
                     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>Do not manage your own JDBC connections:</term>
            <listitem>
                <para>
                    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>
            <listitem>
                <para>
                    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.
                </para>
            </listitem>
        </varlistentry>
        <varlistentry>
            <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. 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>, wrap your JDBC operation as a <literal>org.hibernate.jdbc.Work</literal> object and using 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>
            <listitem>
                <para>
                    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>
            <listitem>
                <para>
                    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>
            <listitem>
                <para>
                    Database Transactions have to be as short as possible for best scalability. However, it is often
                    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 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.
                </para>
            </listitem>
        </varlistentry>
        <varlistentry>
            <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 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>
            <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 join fetching is appropriate to a particular use
                    case, use a query with a <literal>left join fetch</literal>.
                </para>
            </listitem>
        </varlistentry>
        <varlistentry>
            <term>
                Use the <emphasis>open session in view</emphasis> pattern, or a disciplined 
                <emphasis>assembly phase</emphasis> to avoid problems with unfetched data:
            </term>
            <listitem>
                <para>
                    Hibernate frees the developer from writing tedious <emphasis>Data Transfer Objects</emphasis> (DTO). 
                    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. 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>
            <listitem>
                <para>
                    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, however, 
                    intended for "sufficiently large" applications. It is not appropriate for an application with
                    five tables.
                </para>
            </listitem>
        </varlistentry>
        <varlistentry>
            <term>Do not use exotic association mappings:</term>
            <listitem>
                <para>
                    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,
                    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>
            <listitem>
                <para>
                    Unidirectional associations are more difficult to query. In a large application, almost
                    all associations must be navigable in both directions in queries.
                </para>
            </listitem>
        </varlistentry>
    </variablelist>

</chapter>

