This article is more than 1 year old

Hibernate Object Relational Mapping (Part 2)

Second in a two-part series by Java Guru John Hunt

Hibernate Object Relational Mapping (Part 1) is here.

Unlike some frameworks, you do not need to do anything special to your objects to allow them to persist via Hibernate. They can be Plain Old Java Objects (or POJO) objects. These objects can follow the JavaBeans conventions and provide setters and getters. Hibernate will then use reflection to obtain the data required to persist the object.

Step 2: Create a hibernate mapping for any Java objects that must be persisted

Although hibernate uses reflection to obtain data, it still needs to know which elements of an object should be persisted, what their types are and where to put the data when it obtains it (e.g. which database table to put the data in). This is defined in another XML file (one per persistent object); which has an hbm.xml extension. For example, if we want to make a Book class persistent, then we would create a Books.hbm.xml file.

Step 3: Add all class mappings to the <session-factory> element of the hibernate.cfg.xml

Next, we need to tell Hibernate about the individual class mapping fields. Adding mapping elements to the hibernate.cfg.xml file, one for each mapping, does this.

Step 4: Create a class to start Hibernate

Although our standard JavaBean classes do not need to know about Hibernate, we do need to start Hibernate up when we need it and to obtain a reference to an appropriate Hibernate Session</> object. This is done by configuring a new SessionFactory object that is initialised using the hibernate.cfg.xml file; and from this session factory Hibernate session objects can be obtained. A Hibernate Session represents a single-threaded unit of work; the SessionFactory is a thread-safe global object, instantiated once. Note that each thread in an application should be supplied with its own session object.

Step 5: Create a test harness to use the persistent class and Hibernate

This of course may be your main application – in this case, it will be a simple test harness class containing a main method.

The final Hibernate application

In this section, we will follow through the steps presented above for a very simple application. We will create a simple Book JavaBean that we want to persist into a table called books (previously set up in MySQL above).

Step 1: Create the Java Objects

We have defined a new Java class called Book in the package uk.co.planetjava.hibernate.bookstore. This Java class has three instance variables id, title, author and price. It also has setter and getter methods for all the variables. There is nothing Hibernate specific about this class. It is presented below.

Step 2: Create a hibernate mapping for any Java objects that must be persisted.

Next, we need to create the Hibernate mapping file for this class. The file will be called Book.hbm.xml and will be saved into the classes directory structure along with the Book.class file. The XML file is presented below:

Note that in this XML file we have mapped the fully qualified name of the class to the MySQL table books. We have also indicated that the instance variable id will be populated by the database itself (remember the id field was specified as auto-increment in the CREATE TABLE SQL statement). We have also specified the types of the various properties to be stored.

Step 3: Add all class mappings to the <session-factory> element of the hibernate.cfg.xml

Next, we need to add this mapping file to the Hibernate Session factories configuration information. This is done via the hibernate.cfg.xml file and is illustrated below. The new mapping element is highlighted and specifies the location of the mapping file (that is it is located along the class path within the uk/co/planetjava/hibernate/bookstore directory).

Step 4: Create a class to start Hibernate

We will create a very simple class to start up Hibernate. In a real application, you will need to think about threading issues in more detail (see http://caveatemptor.hibernate.org/ for an example). Our simple Hibernate initiation class will be called HibernateSessionFactory. It will initialise the SessionFactory class when it is loaded (static blocks are run when a class is first loaded). It will then create a new session upon request via the getHibernateSession() static method. The class is presented below.

Step 5: Create a test harness to use the persistent class and Hibernate

We are now ready to write our test harness class. This class will start up the Hibernate session and obtain a reference to Hibernate via the HibernateSessionFactory class. It will then create an instance of our book class and populate it with data (leaving the id property null). It will then ask Hibernate to save the object using the session.save(Object o) method. We will then close down hibernate. This is illustrated in Figure 9. Note that the only point at which hibernate and the book object come in contact is when hibernate is asked to save the object.

Before we run this example, we should make sure that the log4j.properties file provided with Hibernate is also on our class path. This will allow Hibernate to provide explanatory logging, which will help indicate what Hibernate is doing. This is aided by the print statements included in our main method of the Main class that help to indicate the stages the test application is going through.

You should now be able to run the uk.co.planetjava.hibernate.bookstore.Main application. If you encounter problems, make sure that everything you need is available on your class path.

To check that what we have done has worked properly, return to your MySQL console and perform a select statement on the books table. This is illustrated in Figure 10. As you can see form this, the data entered into the Java object has made its way into the books table. In addition, the id has been automatically generated.

Note to reload the book data into a book object we would use the id as the primary key, the class to load and the get method on a Hibernate Session object, for example:

Book book = (Book) session.get(Book.class, new Integer(1));

Hibernate and Transactions

In the example presented above in this tutorial, we have not used transactions. Under normal circumstances, it would be appropriate to group a series of operations together into a transaction. A transaction is a unit of work that must either be completed or not executed at all. We usually refer to the Hibernate Session as a unit of work because the scope of a Session is exactly that, in almost all cases. To begin a unit of work you open a Session. To end a unit of work you close a Session. Usually you also flush a Session at the end of a unit of work to execute the SQL statements that synchronize the in-memory Session state with the database. However, for mist real world applications this is not enough. Rather it is better to wrap the Hibernate session within a transaction and either commit it on successful completion of all tasks or roll it back if an error occurs. For example, we could modify the earlier example thus:

Transaction trans = sess.beginTransaction();

try { System.out.println("-------------------------------- Save Book");

session.save(book);

trans.commit();

System.out.println("----------- Close the session ");

sess.close();

} catch (Exception exp) {

System.out.println("Rollback the session");

trans.rollback(); }

Indeed this approach is so common that Hibernate expects the environment (in J2EE servers) to disable auto-commit mode, as applications are not executing ad-hoc SQL but a planned sequence of statements.

Where to go next

You have now created and executed your first Hibernate-based Java application. As you can see this application was very simple, but it provides the basics required to work with Hibernate. In the real world, things get more complex with inter-object relationships, database schemas, multiple tables etc. But all those features build from what you have seen here.

For more information on designing efficient relational database storage for your object data (largely a question of normalisation for flexibility and knowing when to denormalise for performance):

The Open Source tutorials on database design here.

An article on database normalisation here.

Another database normalisation tutorial here.

And a summary of database normalisation rules here.

®

More about

TIP US OFF

Send us news


Other stories you might like