Friday, September 12, 2008

Hibernate 101


Hibernate is an object-relational mapping (ORM) library for the Java language, providing a framework for mapping an object-oriented domain model to a traditional relational database. Hibernate solves Object-Relational impedance mismatch problems by replacing directpersistence-related database accesses with high-level object handling functions.

The canonical "Hello World" example, we introduce the core Hibernate APIs and give details for a basic configuration.

"Hello World" with Hibernate

Hibernate applications define persistent classes that are "mapped" to database tables. Our "Hello World" example consists of one class and one mapping file. Let's see what a simple persistent class looks like, how the mapping is specified, and some of the things we can do with instances of the persistent class using Hibernate.

The objective of our sample application is to store messages in a database and to retrieve them for display. The application has a simple persistent class, Message, which represents these printable messages. Our Message class is shown in Listing 1.

Listing 1. Message.java: A simple persistent class

package hello; public class Message {    private Long id;    private String text;    private Message nextMessage;    private Message() {}    public Message(String text) {       this.text = text;    }    public Long getId() {       return id;    }    private void setId(Long id) {       this.id = id;    }    public String getText() {       return text;    }    public void setText(String text) {       this.text = text;    }    public Message getNextMessage() {       return nextMessage;    }    public void setNextMessage(Message nextMessage) {       this.nextMessage = nextMessage;    } } 


Our Message class has three attributes: the identifier attribute, the text of the message, and a reference to anotherMessage. The identifier attribute allows the application to access the database identity—the primary key value—of a persistent object. If two instances of Message have the same identifier value, they represent the same row in the database. We've chosen Long for the type of our identifier attribute, but this isn't a requirement. Hibernate allows virtually anything for the identifier type, as you'll see later.

You may have noticed that all attributes of the Message class have JavaBean-style property accessor methods. The class also has a constructor with no parameters. The persistent classes we use in our examples will almost always look something like this.

Instances of the Message class may be managed (made persistent) by Hibernate, but they don't have to be. Since theMessage object doesn't implement any Hibernate-specific classes or interfaces, we can use it like any other Java class:

Message message = new Message("Hello World"); System.out.println( message.getText() ); 


This code fragment does exactly what we've come to expect from "Hello World" applications: It prints "Hello World" to the console. It might look like we're trying to be cute here; in fact, we're demonstrating an important feature that distinguishes Hibernate from some other persistence solutions, such as EJB (Enterprise JavaBean) entity beans. Our persistent class can be used in any execution context—no special container is needed. Of course, you came here to see Hibernate itself, so let's save a new Message to the database:

Session session = getSessionFactory().openSession(); Transaction tx = session.beginTransaction(); Message message = new Message("Hello World"); session.save(message); tx.commit(); session.close(); 


This code calls the Hibernate Session and Transaction interfaces. (We'll get to that getSessionFactory() call soon.) It results in the execution of something similar to the following SQL:

insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID) values (1, 'Hello World', null) 


Hold on—the MESSAGE_ID column is being initialized to a strange value. We didn't set the id property of message anywhere, so we would expect it to be null, right? Actually, the id property is special: It's an identifier property—it holds a generated unique value. (We'll discuss how the value is generated later.) The value is assigned to the Message instance by Hibernate when save() is called.

For this example, we assume that the MESSAGES table already exists. Of course, we want our "Hello World" program to print the message to the console. Now that we have a message in the database, we're ready to demonstrate this. The next example retrieves all messages from the database, in alphabetical order, and prints them:

Session newSession = getSessionFactory().openSession(); Transaction newTransaction = newSession.beginTransaction(); List messages =       newSession.find("from Message as m order by m.text asc"); System.out.println( messages.size() + " message(s) found:" ); for ( Iterator iter = messages.iterator(); iter.hasNext(); ) {    Message message = (Message) iter.next();    System.out.println( message.getText() ); } newTransaction.commit(); newSession.close(); 


The literal string "from Message as m order by m.text asc" is a Hibernate query, expressed in Hibernate's own object-oriented Hibernate Query Language (HQL). This query is internally translated into the following SQL when find() is called:

select m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID from MESSAGES m order by m.MESSAGE_TEXT asc 


The code fragment prints:

1 message(s) found: Hello World 


If you've never used an ORM tool like Hibernate before, you were probably expecting to see the SQL statements somewhere in the code or metadata. They aren't there. All SQL is generated at runtime (actually at startup, for all reusable SQL statements).

Courtesy: http://www.javaworld.com/javaworld/jw-10-2004/jw-1018-hibernate.html

http://en.wikipedia.org/wiki/Hibernate_(Java)