More Books
Hibernate: A J2EE Developer's Guide
Hibernate: A J2EE™ Developer's Guide
Table of Contents
Copyright
Acknowledgments
About the Author
Preface
Required Skills
Roadmap
Chapter 1. Overview
Why Object/Relational Mapping?
What Is Hibernate?
Comparing JDBC to Hibernate
Hibernate's Mapping System
Other Java/Database Integration Solutions
How to Obtain and Install
Supported Databases
Chapter 2. Getting Oriented
Application Architecture
Mapping Files
Generating Java Source
Application Configuration
Web Application
JSP Interface
Chapter 3. Starting from Java
Java Object Model
Generated Mapping Files
Generated Schema
Working with Artifacts and Owners
Chapter 4. Starting from an Existing Schema
Initial Schema
Using Middlegen
Generated Mapping Files
Generated Java
Working with the Database
Chapter 5. Mapping Files
Basic Structure
Mapping File Reference
Chapter 6. Persistent Objects
Sessions
Objects and Identity
Life-Cycle Methods
Chapter 7. Relationships
Database Relationships
Java Collection Relationships
Java Class Relationships
Any-Based Relationships
Bi-directional Relationships
Chapter 8. Queries
HQL
HQL Reference
Select
From
Where
Group By
Having
Order By
Criteria Queries
Native SQL Queries
Chapter 9. Transactions
Introduction to Transactions
Optimistic and Pessimistic Locking
Chapter 10. Performance
Finding and Solving Problems
Queries
Inserts
Connection Pooling
Caching
Chapter 11. Schema Management
Updating an Existing Schema
Generating Update and Drop Scripts
Chapter 12. Best Practices, Style Guide, Tips and Tricks
Reducing Code with Inversion of Control
Reducing Session Creation Impact with ThreadLocal
Using Hibernate as an EJB BMP Solution
Integrating with Other Technologies
Applications That Use Hibernate
Strategies for Getting Started
Chapter 13. Future Directions
Hibernate 3.0
EJB 3.0
Here and Now
Index
SYMBOL
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X

Reducing Code with Inversion of Control

Perhaps you wish to use Hibernate in a JSP application (as described in Chapter 2) but are unhappy with the copy-and-paste booking shown for managing transactions. If so, you can use anonymous inner classes to reduce bookkeeping while preserving control. This is popularly referred to as inversion of control, or IoC.

The term inversion of control refers to the notion that your code is handed to another class to actually be executed. Whenever you write code intended to run inside another application, you are, in a sense, inverting (or transferring) control of the execution environment to another system. In particular, the use in Java of anonymous inner classes in conjunction with a framework is dubbed "inversion of control."

Listing 12.1 shows the use of an anonymous inner class to actually perform the database access. Two independent operations are shown. Each operation is performed by an anonymous HibernateSessionWrapper() implementation of the task() method. The first operation demonstrates access to the database, the second is an example of error handling. Note that the code shows no exception-handling strategy; it is subsumed into the underlying HibernateSession Wrapper class.

Listing 12.1. Inversion of Control Example
package com.cascadetg.ch12;

import java.util.Iterator;

public class IoCExample
{

    public static void main(String[] args)
    {
        // Need one global configuration
        HibernateSessionWrapper.initialization();

        // Create our task as an anonymous inner class.
        // Note, no exception handling needed, implicit
        // availability of a session.
        HibernateSessionWrapper myTask = new
        HibernateSessionWrapper()
        {

            Object task(Object in) throws Exception
            {
                net.sf.hibernate.Query myQuery = session
                        .createQuery((String) in);

                Iterator result = myQuery.list().iterator();

                session.flush();
                return result;
            }
        };

        // Execute a bit of HQL and get the results
        Iterator result = (Iterator) myTask
                .perform("from Author");
        while (result.hasNext())
        {
            System.out.println(result.next().toString());
            System.out.flush();
        }

        // Create our task as an anonymous inner class.
        // Note, no exception handling needed, implicit
        // availability of a session.
        HibernateSessionWrapper myTask2 = new
        HibernateSessionWrapper()
        {

            Object task(Object in) throws Exception
            {
                throw new Exception();
            }
        };

        // Do the task.
        if (myTask2.perform() == null)
                System.out.println(myTask2.getException());
    }
}

The anonymous inner class in Listing 12.1 is a subclass of the abstract class shown in Listing 12.2. Only the task() method must be overridden. If the task() method fails because of an exception, the method automatically returns null, and additional methods are provided to determine the precise nature of the exception.

Listing 12.2. Inversion of Control Example
package com.cascadetg.ch12;

import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;

public abstract class HibernateSessionWrapper
{

    /** This method must be overridden to actually do anything
    */
    abstract Object task(Object in) throws Exception;

    Session session = null;

    Transaction transaction = null;

    boolean stale = false;

    Exception problem = null;
    /**
     * Used to identify that a stale object was encountered as
     * part of the transaction.
     */
    public boolean isStaleOperation()
    {
        return stale;
    }

    public Exception getException()
    {
        return problem;
    }

    /** We use this session factory to create our sessions */
    public static SessionFactory sessionFactory;

    /**
     * Loads the Hibernate configuration information, sets up the
     * database and the Hibernate session factory.
     *
     * Should be customized for your application.
     */
    public static void initialization()
    {
        try
        {
            Configuration myConfiguration = new
                 Configuration();
            myConfiguration
                    .addClass(com.cascadetg.ch02.Post.class);
            myConfiguration
                    .addClass(com.cascadetg.ch02.Author.class);

            // Sets up the session factory (used in the rest
            // of the application).
            sessionFactory = myConfiguration
                    .buildSessionFactory();
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public Object perform()
    {
        return perform(null);
    }

    /**
     * Actually does the set-up for the session, as well as
     * execute the task. Handles all of the exceptions (you may
     * wish to customize this per your login preference)
     */
    public Object perform(Object in)
    {
        Object result = null;
        try
        {
            session = sessionFactory.openSession();
            transaction = session.beginTransaction();

            result = task(in);

            transaction.commit();

        } catch (StaleObjectStateException staleException)
        {
            stale = true;
            try
            {
                transaction.rollback();
            } catch (Exception e2)
            {
                e2.printStackTrace();
            }
        } catch (Exception e)
        {
            result = null;
            problem = e;
            e.printStackTrace();
            try
            {
                transaction.rollback();
            } catch (Exception e2)
            {
                // Notify of a failure to roll the transaction
                // back
                e.printStackTrace();
            }
        } finally
        {
            try
            {
                if (session != null) session.close();
            } catch (Exception e)
            {
                // Silent failure of session close
            }
        }
        return result;
    }
}

If you find the inversion of control style of development interesting, you may wish to investigate the Spring framework (http://www.springframework.org/). Spring is a more sophisticated IoC framework than the one shown in Listing 12.2; it provides a number of additional services (both specific to Hibernate and helpful for application development in general).