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

Comparing JDBC to Hibernate

If you are reading this book, you almost certainly have either written or maintained applications in which a surprisingly large amount of code is devoted to maintaining the glue between your Java code and your relational database. (From here on, we'll assume that you have chosen to standardize on Java as your preferred programming language, and on SQL as your preferred relational database language. While object/relational technology is available for a variety of other programming environments, Hibernate is a Java-based system.)

Anyone who has built a Java application using JDBC has experienced the difficulties inherent in the mismatch between Java and SQL. Let's look at an example of retrieving data using JDBC, shown in Listing 1.1.

Listing 1.1. Simple JDBC Code
package com.cascadetg.ch01;

import java.sql.*;

public class JDBCClient
{

    static void printColumn(String in)
    {
        System.out.print(in);
        System.out.print(" | ");
    }
    public static void main(String[] args)
    {
        Driver myDriver = null;
        Connection myConnection = null;
        try
        {
            myDriver = (Driver)Class
                 .forName("com.mysql.jdbc.Driver")
                    .newInstance();

            myConnection = DriverManager.getConnection(
                    "jdbc:mysql://localhost/sample", "root",
                         "");

            Statement myStatement =
                 myConnection.createStatement();

            ResultSet myResults = myStatement.executeQuery(
                    "SELECT ID, weight, name FROM Animal");

            while (myResults.next())
            {
                printColumn(myResults.getLong("ID") + "");
                printColumn(myResults.getInt("weight") + "");
                printColumn(myResults.getString("name"));
                System.out.println();
            }

        } catch (Exception e)
        {
            e.printStackTrace();
        } finally
        {
            try
            {
                if (myConnection != null)
                    myConnection.close();
            } catch (Exception e)
            {
            }
        }
    }
}

As you can see, the retrieval of the individual data is both error-prone and time-consuming. It's very easy to make a mistake in any of the hard-coded strings, and more complex SQL can lead to (possibly inadvertent) database-specific code.

Now let's look at a similar retrieval performed using Hibernate, as shown in Listing 1.2. The output of Listing 1.2 (excluding informational messages provided by Hibernate) is identical to that of Listing 1.1.

Listing 1.2. Simple Hibernate Code
package com.cascadetg.ch01;

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

public class HibernateClient
{
    static String[] props =
        {
            "hibernate.connection.driver_class",
                 "com.mysql.jdbc.Driver",
            "hibernate.connection.url",
                 "jdbc:mysql://localhost/sample",
            "hibernate.connection.username", "root",
            "hibernate.connection.password", "",
            "hibernate.dialect",
                 "net.sf.hibernate.dialect.MySQLDialect",
            "hibernate.show_sql", "true"
        };

    static void printColumn(String in)
    {
        System.out.print(in);
        System.out.print(" | ");
    }

    public static void main(String[] args)
    {
        try
        {
            // One-time only configuration code, run only
            // during application initialization.
            Configuration myConfiguration = new
                  Configuration();
            myConfiguration.addClass(
                com.cascadetg.ch01.Animal.class);
            for (int i = 0; i < props.length; i = i + 2)
                myConfiguration.setProperty(props[i], props[i
                     +1]);

            SessionFactory sessionFactory =
                myConfiguration.buildSessionFactory();

            Session hibernateSession =
                 sessionFactory.openSession();

            Criteria query = hibernateSession.createCriteria(
                    com.cascadetg.ch01.Animal.class);

            // Here we get and loop over the results
            java.util.Iterator results =
                 query.list().iterator();
            while (results.hasNext())
            {
                // Notice that the result set is cast to the
                // Animal
                // object directly - no manual binding
                // required.
                Animal myAnimal = (Animal)results.next();

                printColumn(myAnimal.getId() + "");
                printColumn(myAnimal.getWeight() + "");
                printColumn(myAnimal.getName());
            }
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

The first thing you should notice when examining the code in Listing 1.2 is that there are no hard-coded SQL strings in the query. In addition, there is no need to retrieve data using JDBC result set queries; you simply work with returned Animal objects. In this example, both the Java source for the Animal class and the schema for the corresponding Animal table are generated automatically by Hibernate.

It's possible to express complex relationships, including one-to-many and even many-to-many, using Hibernate, with Hibernate intelligently loading and caching data, automatically generating potentially very complex joins in order to optimally retrieve the data. This binding of the Java code and database schema is known as object/relational mapping.